mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-03 22:38:30 +01:00
Added search hint service
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Lucene.Net.Analysis.Standard;
|
||||
using Lucene.Net.Analysis.Standard;
|
||||
using Lucene.Net.Documents;
|
||||
using Lucene.Net.Index;
|
||||
using Lucene.Net.QueryParsers;
|
||||
@@ -11,8 +6,13 @@ using Lucene.Net.Search;
|
||||
using Lucene.Net.Store;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Library
|
||||
{
|
||||
@@ -22,15 +22,22 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
/// </summary>
|
||||
public class LuceneSearchEngine : ILibrarySearchEngine, IDisposable
|
||||
{
|
||||
public LuceneSearchEngine(IServerApplicationPaths serverPaths, ILogManager logManager)
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public LuceneSearchEngine(IServerApplicationPaths serverPaths, ILogManager logManager, ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
|
||||
_logger = logManager.GetLogger("Lucene");
|
||||
|
||||
//string luceneDbPath = serverPaths.DataPath + "\\SearchIndexDB";
|
||||
//if (!System.IO.Directory.Exists(luceneDbPath))
|
||||
// System.IO.Directory.CreateDirectory(luceneDbPath);
|
||||
//else if(File.Exists(luceneDbPath + "\\write.lock"))
|
||||
// File.Delete(luceneDbPath + "\\write.lock");
|
||||
|
||||
//LuceneSearch.Init(luceneDbPath, logManager.GetLogger("Lucene"));
|
||||
//LuceneSearch.Init(luceneDbPath, _logger);
|
||||
|
||||
//BaseItem.LibraryManager.LibraryChanged += LibraryChanged;
|
||||
}
|
||||
@@ -82,6 +89,164 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
//LuceneSearch.CloseAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the search hints.
|
||||
/// </summary>
|
||||
/// <param name="inputItems">The input items.</param>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <returns>IEnumerable{SearchHintResult}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">searchTerm</exception>
|
||||
public async Task<IEnumerable<BaseItem>> GetSearchHints(IEnumerable<BaseItem> inputItems, string searchTerm)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchTerm))
|
||||
{
|
||||
throw new ArgumentNullException("searchTerm");
|
||||
}
|
||||
|
||||
var hints = new List<Tuple<BaseItem, int>>();
|
||||
|
||||
var items = inputItems.Where(i => !(i is MusicArtist)).ToList();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var index = IndexOf(item.Name, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
hints.Add(new Tuple<BaseItem, int>(item, index));
|
||||
}
|
||||
}
|
||||
|
||||
var artists = items.OfType<Audio>()
|
||||
.SelectMany(i => new[] { i.Artist, i.AlbumArtist })
|
||||
.Where(i => !string.IsNullOrEmpty(i))
|
||||
.ToList();
|
||||
|
||||
foreach (var item in artists)
|
||||
{
|
||||
var index = IndexOf(item, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var artist = await _libraryManager.GetArtist(item).ConfigureAwait(false);
|
||||
|
||||
hints.Add(new Tuple<BaseItem, int>(artist, index));
|
||||
}
|
||||
}
|
||||
|
||||
// Find genres
|
||||
var genres = items.SelectMany(i => i.Genres)
|
||||
.Where(i => !string.IsNullOrEmpty(i))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
foreach (var item in genres)
|
||||
{
|
||||
var index = IndexOf(item, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var genre = await _libraryManager.GetGenre(item).ConfigureAwait(false);
|
||||
|
||||
hints.Add(new Tuple<BaseItem, int>(genre, index));
|
||||
}
|
||||
}
|
||||
|
||||
// Find studios
|
||||
var studios = items.SelectMany(i => i.Studios)
|
||||
.Where(i => !string.IsNullOrEmpty(i))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
foreach (var item in studios)
|
||||
{
|
||||
var index = IndexOf(item, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var studio = await _libraryManager.GetStudio(item).ConfigureAwait(false);
|
||||
|
||||
hints.Add(new Tuple<BaseItem, int>(studio, index));
|
||||
}
|
||||
}
|
||||
|
||||
// Find persons
|
||||
var persons = items.SelectMany(i => i.People)
|
||||
.Select(i => i.Name)
|
||||
.Where(i => !string.IsNullOrEmpty(i))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
foreach (var item in persons)
|
||||
{
|
||||
var index = IndexOf(item, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var person = await _libraryManager.GetPerson(item).ConfigureAwait(false);
|
||||
|
||||
hints.Add(new Tuple<BaseItem, int>(person, index));
|
||||
}
|
||||
}
|
||||
|
||||
return hints.OrderBy(i => i.Item2).Select(i => i.Item1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hints.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <returns>IEnumerable{Tuple{SearchHintResultSystem.Int32}}.</returns>
|
||||
private async Task<IEnumerable<Tuple<BaseItem, int>>> GetHints(BaseItem item, string searchTerm)
|
||||
{
|
||||
var hints = new List<Tuple<BaseItem, int>>();
|
||||
|
||||
var index = IndexOf(item.Name, searchTerm);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
hints.Add(new Tuple<BaseItem, int>(item, index));
|
||||
}
|
||||
|
||||
return hints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the words.
|
||||
/// </summary>
|
||||
/// <param name="term">The term.</param>
|
||||
/// <returns>System.String[][].</returns>
|
||||
private string[] GetWords(string term)
|
||||
{
|
||||
// TODO: Improve this to be more accurate and respect culture
|
||||
var words = term.Split(' ');
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indexes the of.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <param name="term">The term.</param>
|
||||
/// <returns>System.Int32.</returns>
|
||||
private int IndexOf(string input, string term)
|
||||
{
|
||||
var index = 0;
|
||||
|
||||
foreach (var word in GetWords(input))
|
||||
{
|
||||
if (word.IndexOf(term, StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LuceneSearch
|
||||
|
||||
Reference in New Issue
Block a user