Browse Source

add chapters to search index (#2199)

pull/2201/head
Jason Dove 10 months ago committed by GitHub
parent
commit
dd9a6d5a06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 28
      ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs
  3. 1
      ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs
  4. 3
      ErsatzTV.Infrastructure/Search/ElasticSearchIndex.cs
  5. 5
      ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs
  6. 3
      ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs

1
CHANGELOG.md

@ -114,6 +114,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -114,6 +114,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `duration`: when the content is live and does not have duration metadata, this must be provided to allow scheduling
- The remote stream definition (YAML file) may provide either a `url` or a `script`
- If both are provided, `url` will be used
- Include number of chapters in search index as `chapters`
### Changed
- Allow `Other Video` libraries and `Image` libraries to use the same folders

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

@ -35,6 +35,8 @@ public class SearchRepository : ISearchRepository @@ -35,6 +35,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Movie).MovieMetadata)
.ThenInclude(em => em.Guids)
.Include(mi => (mi as Movie).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Movie).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Episode).EpisodeMetadata)
.ThenInclude(em => em.Genres)
@ -51,6 +53,8 @@ public class SearchRepository : ISearchRepository @@ -51,6 +53,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Episode).EpisodeMetadata)
.ThenInclude(em => em.Guids)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(em => em.Streams)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(em => em.MediaFiles)
@ -108,6 +112,8 @@ public class SearchRepository : ISearchRepository @@ -108,6 +112,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as MusicVideo).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as MusicVideo).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Artist).ArtistMetadata)
.ThenInclude(mm => mm.Genres)
@ -132,6 +138,8 @@ public class SearchRepository : ISearchRepository @@ -132,6 +138,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as OtherVideo).OtherVideoMetadata)
.ThenInclude(ovm => ovm.Guids)
.Include(mi => (mi as OtherVideo).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as OtherVideo).MediaVersions)
.ThenInclude(ovm => ovm.Streams)
.Include(mi => (mi as Song).SongMetadata)
.ThenInclude(mm => mm.Tags)
@ -140,6 +148,8 @@ public class SearchRepository : ISearchRepository @@ -140,6 +148,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Song).SongMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as Song).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Song).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Image).ImageMetadata)
.ThenInclude(mm => mm.Tags)
@ -148,6 +158,8 @@ public class SearchRepository : ISearchRepository @@ -148,6 +158,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Image).ImageMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mm => mm.MediaFiles)
@ -158,6 +170,8 @@ public class SearchRepository : ISearchRepository @@ -158,6 +170,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as RemoteStream).RemoteStreamMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mm => mm.MediaFiles)
@ -271,6 +285,8 @@ public class SearchRepository : ISearchRepository @@ -271,6 +285,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Movie).MovieMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as Movie).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Movie).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Episode).EpisodeMetadata)
.ThenInclude(em => em.Genres)
@ -287,6 +303,8 @@ public class SearchRepository : ISearchRepository @@ -287,6 +303,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Episode).EpisodeMetadata)
.ThenInclude(em => em.Guids)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(em => em.Streams)
.Include(mi => (mi as Episode).MediaVersions)
.ThenInclude(em => em.MediaFiles)
@ -344,6 +362,8 @@ public class SearchRepository : ISearchRepository @@ -344,6 +362,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as MusicVideo).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as MusicVideo).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Artist).ArtistMetadata)
.ThenInclude(mm => mm.Genres)
@ -368,6 +388,8 @@ public class SearchRepository : ISearchRepository @@ -368,6 +388,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as OtherVideo).OtherVideoMetadata)
.ThenInclude(ovm => ovm.Guids)
.Include(mi => (mi as OtherVideo).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as OtherVideo).MediaVersions)
.ThenInclude(ovm => ovm.Streams)
.Include(mi => (mi as Song).SongMetadata)
.ThenInclude(mm => mm.Tags)
@ -376,6 +398,8 @@ public class SearchRepository : ISearchRepository @@ -376,6 +398,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Song).SongMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as Song).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Song).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Image).ImageMetadata)
.ThenInclude(mm => mm.Tags)
@ -384,6 +408,8 @@ public class SearchRepository : ISearchRepository @@ -384,6 +408,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as Image).ImageMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as Image).MediaVersions)
.ThenInclude(mm => mm.MediaFiles)
@ -394,6 +420,8 @@ public class SearchRepository : ISearchRepository @@ -394,6 +420,8 @@ public class SearchRepository : ISearchRepository
.Include(mi => (mi as RemoteStream).RemoteStreamMetadata)
.ThenInclude(mm => mm.Guids)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mv => mv.Chapters)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mm => mm.Streams)
.Include(mi => (mi as RemoteStream).MediaVersions)
.ThenInclude(mm => mm.MediaFiles)

1
ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs

@ -14,6 +14,7 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser @@ -14,6 +14,7 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser
{
private static readonly List<string> NumericFields =
[
LuceneSearchIndex.ChaptersField,
LuceneSearchIndex.MinutesField,
LuceneSearchIndex.SecondsField,
LuceneSearchIndex.HeightField,

3
ErsatzTV.Infrastructure/Search/ElasticSearchIndex.cs

@ -49,7 +49,7 @@ public class ElasticSearchIndex : ISearchIndex @@ -49,7 +49,7 @@ public class ElasticSearchIndex : ISearchIndex
return exists.IsValidResponse;
}
public int Version => 47;
public int Version => 48;
public async Task<bool> Initialize(
ILocalFileSystem localFileSystem,
@ -926,6 +926,7 @@ public class ElasticSearchIndex : ISearchIndex @@ -926,6 +926,7 @@ public class ElasticSearchIndex : ISearchIndex
{
foreach (MediaVersion version in mediaVersions.HeadOrNone())
{
doc.Chapters = (version.Chapters ?? []).Count;
doc.Minutes = (int)Math.Ceiling(version.Duration.TotalMinutes);
doc.Seconds = (int)Math.Ceiling(version.Duration.TotalSeconds);

5
ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs

@ -79,6 +79,7 @@ public sealed class LuceneSearchIndex : ISearchIndex @@ -79,6 +79,7 @@ public sealed class LuceneSearchIndex : ISearchIndex
internal const string AddedDateField = "added_date";
internal const string ReleaseDateField = "release_date";
internal const string VideoBitDepthField = "video_bit_depth";
internal const string ChaptersField = "chapters";
public const string MovieType = "movie";
public const string ShowType = "show";
@ -118,7 +119,7 @@ public sealed class LuceneSearchIndex : ISearchIndex @@ -118,7 +119,7 @@ public sealed class LuceneSearchIndex : ISearchIndex
return Task.FromResult(directoryExists && fileExists);
}
public int Version => 48;
public int Version => 49;
public async Task<bool> Initialize(
ILocalFileSystem localFileSystem,
@ -1508,6 +1509,8 @@ public sealed class LuceneSearchIndex : ISearchIndex @@ -1508,6 +1509,8 @@ public sealed class LuceneSearchIndex : ISearchIndex
{
foreach (MediaVersion version in mediaVersions)
{
doc.Add(new Int32Field(ChaptersField, (version.Chapters ?? []).Count, Field.Store.NO));
doc.Add(new Int32Field(MinutesField, (int)Math.Ceiling(version.Duration.TotalMinutes), Field.Store.NO));
doc.Add(new Int32Field(SecondsField, (int)Math.Ceiling(version.Duration.TotalSeconds), Field.Store.NO));

3
ErsatzTV.Infrastructure/Search/Models/ElasticSearchItem.cs

@ -37,6 +37,9 @@ public class ElasticSearchItem : MinimalElasticSearchItem @@ -37,6 +37,9 @@ public class ElasticSearchItem : MinimalElasticSearchItem
[JsonPropertyName(LuceneSearchIndex.SubLanguageTagField)]
public List<string> SubLanguageTag { get; set; }
[JsonPropertyName(LuceneSearchIndex.ChaptersField)]
public int Chapters { get; set; }
[JsonPropertyName(LuceneSearchIndex.MinutesField)]
public int Minutes { get; set; }

Loading…
Cancel
Save