using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Library
{
///
/// Class LuceneSearchEngine
/// http://www.codeproject.com/Articles/320219/Lucene-Net-ultra-fast-search-for-MVC-or-WebForms
///
public class SearchEngine : ISearchEngine
{
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
public SearchEngine(ILogManager logManager, ILibraryManager libraryManager, IUserManager userManager)
{
_libraryManager = libraryManager;
_userManager = userManager;
_logger = logManager.GetLogger("Lucene");
}
public async Task> GetSearchHints(SearchQuery query)
{
IEnumerable inputItems;
if (string.IsNullOrWhiteSpace(query.UserId))
{
inputItems = _libraryManager.RootFolder.RecursiveChildren;
}
else
{
var user = _userManager.GetUserById(query.UserId);
inputItems = user.RootFolder.GetRecursiveChildren(user, true);
}
inputItems = inputItems.Where(i => !(i is ICollectionFolder));
inputItems = _libraryManager.ReplaceVideosWithPrimaryVersions(inputItems);
var results = await GetSearchHints(inputItems, query).ConfigureAwait(false);
// Include item types
if (query.IncludeItemTypes.Length > 0)
{
results = results.Where(f => query.IncludeItemTypes.Contains(f.Item.GetType().Name, StringComparer.OrdinalIgnoreCase));
}
var searchResultArray = results.ToArray();
results = searchResultArray;
var count = searchResultArray.Length;
if (query.StartIndex.HasValue)
{
results = results.Skip(query.StartIndex.Value);
}
if (query.Limit.HasValue)
{
results = results.Take(query.Limit.Value);
}
return new QueryResult
{
TotalRecordCount = count,
Items = results.ToArray()
};
}
///
/// Gets the search hints.
///
/// The input items.
/// The query.
/// IEnumerable{SearchHintResult}.
/// searchTerm
private Task> GetSearchHints(IEnumerable inputItems, SearchQuery query)
{
var searchTerm = query.SearchTerm;
if (string.IsNullOrWhiteSpace(searchTerm))
{
throw new ArgumentNullException("searchTerm");
}
var terms = GetWords(searchTerm);
var hints = new List>();
var items = inputItems.Where(i => !(i is MusicArtist)).ToList();
if (query.IncludeMedia)
{
// Add search hints based on item name
hints.AddRange(items.Where(i => !string.IsNullOrWhiteSpace(i.Name) && IncludeInSearch(i)).Select(item =>
{
var index = GetIndex(item.Name, searchTerm, terms);
return new Tuple(item, index.Item1, index.Item2);
}));
}
if (query.IncludeArtists)
{
// Find artists
var artists = items.OfType