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