Browse Source

add more search fields (#769)

pull/770/head
Jason Dove 3 years ago committed by GitHub
parent
commit
17f540dc99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 8
      ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs
  3. 10
      ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs
  4. 1
      ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs
  5. 8
      ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs
  6. 8
      ErsatzTV.Core/Metadata/MovieFolderScanner.cs
  7. 16
      ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs
  8. 8
      ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs
  9. 8
      ErsatzTV.Core/Metadata/SongFolderScanner.cs
  10. 12
      ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs
  11. 4
      ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs
  12. 17
      ErsatzTV.Infrastructure/Search/SearchIndex.cs
  13. 11
      docs/user-guide/search.md

2
CHANGELOG.md

@ -20,6 +20,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -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

8
ErsatzTV.Application/MediaCollections/Commands/DeleteTraktListHandler.cs

@ -56,13 +56,7 @@ public class DeleteTraktListHandler : TraktCommandBase, IRequestHandler<DeleteTr @@ -56,13 +56,7 @@ public class DeleteTraktListHandler : TraktCommandBase, IRequestHandler<DeleteTr
dbContext.TraktLists.Remove(traktList);
if (await dbContext.SaveChangesAsync() > 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();

10
ErsatzTV.Application/MediaCollections/Commands/TraktCommandBase.cs

@ -156,15 +156,9 @@ public abstract class TraktCommandBase @@ -156,15 +156,9 @@ public abstract class TraktCommandBase
}
}
await dbContext.SaveChangesAsync();
foreach (int mediaItemId in ids)
if (await dbContext.SaveChangesAsync() > 0)
{
Option<MediaItem> 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();

1
ErsatzTV.Core/Interfaces/Search/ISearchIndex.cs

@ -11,7 +11,6 @@ public interface ISearchIndex : IDisposable @@ -11,7 +11,6 @@ public interface ISearchIndex : IDisposable
Task<bool> Initialize(ILocalFileSystem localFileSystem);
Task<Unit> Rebuild(ISearchRepository searchRepository);
Task<Unit> RebuildItems(ISearchRepository searchRepository, List<int> itemIds);
Task<Unit> AddItems(ISearchRepository searchRepository, List<MediaItem> items);
Task<Unit> UpdateItems(ISearchRepository searchRepository, List<MediaItem> items);
Task<Unit> RemoveItems(List<int> ids);
Task<SearchResult> Search(string query, int skip, int limit, string searchField = "");

8
ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs

@ -157,13 +157,9 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib @@ -157,13 +157,9 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib
}
}
if (result.IsAdded)
if (result.IsAdded || result.IsUpdated)
{
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
}
}

8
ErsatzTV.Core/Metadata/MovieFolderScanner.cs

@ -158,13 +158,9 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner @@ -158,13 +158,9 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner
foreach (MediaItemScanResult<Movie> result in maybeMovie.RightToSeq())
{
if (result.IsAdded)
if (result.IsAdded || result.IsUpdated)
{
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
await _libraryRepository.SetEtag(libraryPath, knownFolder, movieFolder, etag);

16
ErsatzTV.Core/Metadata/MusicVideoFolderScanner.cs

@ -135,13 +135,9 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan @@ -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<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
}
}
@ -329,13 +325,9 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan @@ -329,13 +325,9 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan
foreach (MediaItemScanResult<MusicVideo> result in maybeMusicVideo.RightToSeq())
{
if (result.IsAdded)
{
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { result.Item });
}
else if (result.IsUpdated)
if (result.IsAdded || result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
await _libraryRepository.SetEtag(libraryPath, knownFolder, musicVideoFolder, etag);

8
ErsatzTV.Core/Metadata/OtherVideoFolderScanner.cs

@ -152,13 +152,9 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan @@ -152,13 +152,9 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan
foreach (MediaItemScanResult<OtherVideo> result in maybeVideo.RightToSeq())
{
if (result.IsAdded)
if (result.IsAdded || result.IsUpdated)
{
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
await _libraryRepository.SetEtag(libraryPath, knownFolder, otherVideoFolder, etag);

8
ErsatzTV.Core/Metadata/SongFolderScanner.cs

@ -150,13 +150,9 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner @@ -150,13 +150,9 @@ public class SongFolderScanner : LocalFolderScanner, ISongFolderScanner
foreach (MediaItemScanResult<Song> result in maybeSong.RightToSeq())
{
if (result.IsAdded)
if (result.IsAdded || result.IsUpdated)
{
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
await _libraryRepository.SetEtag(libraryPath, knownFolder, songFolder, etag);

12
ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs

@ -125,13 +125,9 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -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<MediaItem> { result.Item });
}
else if (result.IsUpdated)
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { result.Item });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { result.Item.Id });
}
}
}
@ -245,7 +241,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -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<MediaItem> { season });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { season.Id });
}
}
}
@ -291,7 +287,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -291,7 +287,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
foreach (Episode episode in maybeEpisode.RightToSeq())
{
await _searchIndex.UpdateItems(_searchRepository, new List<MediaItem> { episode });
await _searchIndex.RebuildItems(_searchRepository, new List<int> { episode.Id });
}
}

4
ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs

@ -50,6 +50,8 @@ public class SearchRepository : ISearchRepository @@ -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 @@ -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)

17
ErsatzTV.Infrastructure/Search/SearchIndex.cs

@ -49,10 +49,12 @@ public sealed class SearchIndex : ISearchIndex @@ -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 @@ -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<CultureInfo> _cultureInfos;
private readonly ILogger<SearchIndex> _logger;
@ -81,7 +84,7 @@ public sealed class SearchIndex : ISearchIndex @@ -81,7 +84,7 @@ public sealed class SearchIndex : ISearchIndex
_initialized = false;
}
public int Version => 21;
public int Version => 22;
public Task<bool> Initialize(ILocalFileSystem localFileSystem)
{
@ -100,9 +103,6 @@ public sealed class SearchIndex : ISearchIndex @@ -100,9 +103,6 @@ public sealed class SearchIndex : ISearchIndex
return Task.FromResult(_initialized);
}
public Task<Unit> AddItems(ISearchRepository searchRepository, List<MediaItem> items) =>
UpdateItems(searchRepository, items);
public async Task<Unit> UpdateItems(ISearchRepository searchRepository, List<MediaItem> items)
{
foreach (MediaItem item in items)
@ -554,7 +554,9 @@ public sealed class SearchIndex : ISearchIndex @@ -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<string> languages = await searchRepository.GetLanguagesForSeason(season);
@ -767,7 +769,8 @@ public sealed class SearchIndex : ISearchIndex @@ -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);

11
docs/user-guide/search.md

@ -47,6 +47,16 @@ The following fields are available for searching shows: @@ -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: @@ -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

Loading…
Cancel
Save