using MediaBrowser.Common.Extensions; 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; Func filter = i => !(i is ICollectionFolder); User user = null; if (string.IsNullOrWhiteSpace(query.UserId)) { inputItems = _libraryManager.RootFolder.GetRecursiveChildren(filter); } else { user = _userManager.GetUserById(query.UserId); inputItems = user.RootFolder.GetRecursiveChildren(user, filter); } inputItems = _libraryManager.ReplaceVideosWithPrimaryVersions(inputItems); var results = await GetSearchHints(inputItems, query, user).ConfigureAwait(false); 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. /// The user. /// IEnumerable{SearchHintResult}. /// searchTerm private Task> GetSearchHints(IEnumerable inputItems, SearchQuery query, User user) { var searchTerm = query.SearchTerm; if (string.IsNullOrWhiteSpace(searchTerm)) { throw new ArgumentNullException("searchTerm"); } searchTerm = searchTerm.RemoveDiacritics(); var terms = GetWords(searchTerm); var hints = new List>(); var items = inputItems.Where(i => !(i is MusicArtist)).ToList(); if (query.IncludeMedia) { var mediaItems = _libraryManager.GetItems(new InternalItemsQuery { NameContains = searchTerm, ExcludeItemTypes = new[] { typeof (Person).Name, typeof (Genre).Name, typeof (MusicArtist).Name, typeof (GameGenre).Name, typeof (MusicGenre).Name, typeof (Year).Name, typeof (Studio).Name }, IncludeItemTypes = query.IncludeItemTypes }).Items; // Add search hints based on item name hints.AddRange(mediaItems.Where(i => IncludeInSearch(i) && (user == null || i.IsVisibleStandalone(user)) && !(i is CollectionFolder)).Select(item => { var index = GetIndex(item.Name, searchTerm, terms); return new Tuple(item, index.Item1, index.Item2); })); } if (query.IncludeArtists && (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase))) { // Find artists var artists = items.OfType