From 17f540dc9910521e1ca72d63fc3d4a83dfc9729a Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Thu, 28 Apr 2022 10:40:27 -0500 Subject: [PATCH] add more search fields (#769) --- CHANGELOG.md | 2 ++ .../Commands/DeleteTraktListHandler.cs | 8 +------- .../Commands/TraktCommandBase.cs | 10 ++-------- ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs | 1 - .../Metadata/MediaServerMovieLibraryScanner.cs | 8 ++------ ErsatzTV.Core/Metadata/MovieFolderScanner.cs | 8 ++------ .../Metadata/MusicVideoFolderScanner.cs | 16 ++++------------ .../Metadata/OtherVideoFolderScanner.cs | 8 ++------ ErsatzTV.Core/Metadata/SongFolderScanner.cs | 8 ++------ .../Metadata/TelevisionFolderScanner.cs | 12 ++++-------- .../Data/Repositories/SearchRepository.cs | 4 ++++ ErsatzTV.Infrastructure/Search/SearchIndex.cs | 17 ++++++++++------- docs/user-guide/search.md | 11 +++++++++++ 13 files changed, 46 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f9c70482..60da6e6eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add `unavailable` state for Emby movie libraries - Add `height` and `width` to search index for all videos - Add `season_number` and `episode_number` to search index for all episodes +- Add `season_number` to search index for seasons +- Add `show_title` to search index for seasons and episodes ## [0.5.3-beta] - 2022-04-24 ### Fixed diff --git a/ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs index f623ad40f..a038a45bf 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs @@ -56,13 +56,7 @@ public class DeleteTraktListHandler : TraktCommandBase, IRequestHandler 0) { - foreach (int mediaItemId in mediaItemIds) - { - foreach (MediaItem mediaItem in await _searchRepository.GetItemToIndex(mediaItemId)) - { - await _searchIndex.UpdateItems(_searchRepository, new[] { mediaItem }.ToList()); - } - } + await _searchIndex.RebuildItems(_searchRepository, mediaItemIds); } _searchIndex.Commit(); diff --git a/ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs b/ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs index 9ccaa8e88..633814be2 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs @@ -156,15 +156,9 @@ public abstract class TraktCommandBase } } - await dbContext.SaveChangesAsync(); - - foreach (int mediaItemId in ids) + if (await dbContext.SaveChangesAsync() > 0) { - Option maybeItem = await _searchRepository.GetItemToIndex(mediaItemId); - foreach (MediaItem item in maybeItem) - { - await _searchIndex.UpdateItems(_searchRepository, new[] { item }.ToList()); - } + await _searchIndex.RebuildItems(_searchRepository, ids.ToList()); } _searchIndex.Commit(); diff --git a/ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs b/ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs index 4eaa76b19..4607128d8 100644 --- a/ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs +++ b/ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs @@ -11,7 +11,6 @@ public interface ISearchIndex : IDisposable Task Initialize(ILocalFileSystem localFileSystem); Task Rebuild(ISearchRepository searchRepository); Task RebuildItems(ISearchRepository searchRepository, List itemIds); - Task AddItems(ISearchRepository searchRepository, List items); Task UpdateItems(ISearchRepository searchRepository, List items); Task RemoveItems(List ids); Task Search(string query, int skip, int limit, string searchField = ""); diff --git a/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs b/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs index 0388109ac..b150d5d5d 100644 --- a/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs +++ b/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs @@ -157,13 +157,9 @@ public abstract class MediaServerMovieLibraryScanner { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } } } diff --git a/ErsatzTV.Core/Metadata/MovieFolderScanner.cs b/ErsatzTV.Core/Metadata/MovieFolderScanner.cs index 81264a418..e0882693d 100644 --- a/ErsatzTV.Core/Metadata/MovieFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/MovieFolderScanner.cs @@ -158,13 +158,9 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner foreach (MediaItemScanResult result in maybeMovie.RightToSeq()) { - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } await _libraryRepository.SetEtag(libraryPath, knownFolder, movieFolder, etag); diff --git a/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs b/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs index 7758acc76..d43e32f8d 100644 --- a/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs @@ -135,13 +135,9 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan return error; } - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } } } @@ -329,13 +325,9 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan foreach (MediaItemScanResult result in maybeMusicVideo.RightToSeq()) { - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } await _libraryRepository.SetEtag(libraryPath, knownFolder, musicVideoFolder, etag); diff --git a/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs b/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs index 2a1adec1a..f4c2b5104 100644 --- a/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs @@ -152,13 +152,9 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan foreach (MediaItemScanResult result in maybeVideo.RightToSeq()) { - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } await _libraryRepository.SetEtag(libraryPath, knownFolder, otherVideoFolder, etag); diff --git a/ErsatzTV.Core/Metadata/SongFolderScanner.cs b/ErsatzTV.Core/Metadata/SongFolderScanner.cs index 19551a474..f0245b924 100644 --- a/ErsatzTV.Core/Metadata/SongFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/SongFolderScanner.cs @@ -150,13 +150,9 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner foreach (MediaItemScanResult result in maybeSong.RightToSeq()) { - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } await _libraryRepository.SetEtag(libraryPath, knownFolder, songFolder, etag); diff --git a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs index e7b992d90..447c1f54d 100644 --- a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs @@ -125,13 +125,9 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan return error; } - if (result.IsAdded) + if (result.IsAdded || result.IsUpdated) { - await _searchIndex.AddItems(_searchRepository, new List { result.Item }); - } - else if (result.IsUpdated) - { - await _searchIndex.UpdateItems(_searchRepository, new List { result.Item }); + await _searchIndex.RebuildItems(_searchRepository, new List { result.Item.Id }); } } } @@ -245,7 +241,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan await _libraryRepository.SetEtag(libraryPath, knownFolder, seasonFolder, etag); season.Show = show; - await _searchIndex.UpdateItems(_searchRepository, new List { season }); + await _searchIndex.RebuildItems(_searchRepository, new List { season.Id }); } } } @@ -291,7 +287,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan foreach (Episode episode in maybeEpisode.RightToSeq()) { - await _searchIndex.UpdateItems(_searchRepository, new List { episode }); + await _searchIndex.RebuildItems(_searchRepository, new List { episode.Id }); } } diff --git a/ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs index 95425f096..2a60202ba 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs @@ -50,6 +50,8 @@ public class SearchRepository : ISearchRepository .Include(mi => (mi as Episode).MediaVersions) .ThenInclude(em => em.Streams) .Include(mi => (mi as Episode).Season) + .ThenInclude(s => s.Show) + .ThenInclude(s => s.ShowMetadata) .Include(mi => (mi as Season).SeasonMetadata) .ThenInclude(sm => sm.Genres) .Include(mi => (mi as Season).SeasonMetadata) @@ -181,6 +183,8 @@ public class SearchRepository : ISearchRepository .Include(mi => (mi as Episode).MediaVersions) .ThenInclude(em => em.Streams) .Include(mi => (mi as Episode).Season) + .ThenInclude(s => s.Show) + .ThenInclude(s => s.ShowMetadata) .Include(mi => (mi as Season).SeasonMetadata) .ThenInclude(sm => sm.Genres) .Include(mi => (mi as Season).SeasonMetadata) diff --git a/ErsatzTV.Infrastructure/Search/SearchIndex.cs b/ErsatzTV.Infrastructure/Search/SearchIndex.cs index 56410995d..0aab72cdd 100644 --- a/ErsatzTV.Infrastructure/Search/SearchIndex.cs +++ b/ErsatzTV.Infrastructure/Search/SearchIndex.cs @@ -49,10 +49,12 @@ public sealed class SearchIndex : ISearchIndex private const string WriterField = "writer"; private const string TraktListField = "trakt_list"; private const string AlbumField = "album"; - internal const string MinutesField = "minutes"; private const string ArtistField = "artist"; private const string StateField = "state"; private const string AlbumArtistField = "album_artist"; + private const string ShowTitleField = "show_title"; + + internal const string MinutesField = "minutes"; internal const string HeightField = "height"; internal const string WidthField = "width"; internal const string SeasonNumberField = "season_number"; @@ -66,6 +68,7 @@ public sealed class SearchIndex : ISearchIndex public const string EpisodeType = "episode"; public const string OtherVideoType = "other_video"; public const string SongType = "song"; + private readonly List _cultureInfos; private readonly ILogger _logger; @@ -81,7 +84,7 @@ public sealed class SearchIndex : ISearchIndex _initialized = false; } - public int Version => 21; + public int Version => 22; public Task Initialize(ILocalFileSystem localFileSystem) { @@ -100,9 +103,6 @@ public sealed class SearchIndex : ISearchIndex return Task.FromResult(_initialized); } - public Task AddItems(ISearchRepository searchRepository, List items) => - UpdateItems(searchRepository, items); - public async Task UpdateItems(ISearchRepository searchRepository, List items) { foreach (MediaItem item in items) @@ -554,7 +554,9 @@ public sealed class SearchIndex : ISearchIndex new StringField(LibraryIdField, season.LibraryPath.Library.Id.ToString(), Field.Store.NO), new StringField(TitleAndYearField, titleAndYear, Field.Store.NO), new StringField(JumpLetterField, GetJumpLetter(showMetadata), Field.Store.YES), - new StringField(StateField, season.State.ToString(), Field.Store.NO) + new StringField(StateField, season.State.ToString(), Field.Store.NO), + new Int32Field(SeasonNumberField, season.SeasonNumber, Field.Store.NO), + new TextField(ShowTitleField, season.Show?.ShowMetadata.Head().Title, Field.Store.NO) }; List languages = await searchRepository.GetLanguagesForSeason(season); @@ -767,7 +769,8 @@ public sealed class SearchIndex : ISearchIndex new StringField(JumpLetterField, GetJumpLetter(metadata), Field.Store.YES), new StringField(StateField, episode.State.ToString(), Field.Store.NO), new Int32Field(SeasonNumberField, episode.Season?.SeasonNumber ?? 0, Field.Store.NO), - new Int32Field(EpisodeNumberField, metadata.EpisodeNumber, Field.Store.NO) + new Int32Field(EpisodeNumberField, metadata.EpisodeNumber, Field.Store.NO), + new TextField(ShowTitleField, episode.Season?.Show?.ShowMetadata.Head().Title, Field.Store.NO) }; await AddLanguages(searchRepository, doc, episode.MediaVersions); diff --git a/docs/user-guide/search.md b/docs/user-guide/search.md index f2d15edc9..82039d3a4 100644 --- a/docs/user-guide/search.md +++ b/docs/user-guide/search.md @@ -47,6 +47,16 @@ The following fields are available for searching shows: - `added_date`: The date the show was added to ErsatzTV (YYYYMMDD) - `type`: Always `show` +### Seasons + +The following fields are available for searching seasons: + +- `title`: The season title +- `library_name`: The name of the library that contains the season +- `season_number`: The season number +- `show_title`: The title of the show that contains the season +- `type`: Always `season` + ### Episodes The following fields are available for searching episodes: @@ -64,6 +74,7 @@ The following fields are available for searching episodes: - `width`: The episode width - `season_number`: The episode season number - `episode_number`: The episode number +- `show_title`: The title of the show that contains the episode - `type`: Always `episode` ### Artists