mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Creating views for library items
This commit is contained in:
parent
531abee95b
commit
0c537e1cc1
@ -74,6 +74,14 @@ namespace Kyoo
|
|||||||
/// Episodes with a watch percentage. See <see cref="WatchedEpisode"/>
|
/// Episodes with a watch percentage. See <see cref="WatchedEpisode"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DbSet<WatchedEpisode> WatchedEpisodes { get; set; }
|
public DbSet<WatchedEpisode> WatchedEpisodes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of library items (shows and collections that are part of a library - or the global one)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This set is ready only, on most database this will be a view.
|
||||||
|
/// </remarks>
|
||||||
|
public DbSet<LibraryItem> LibraryItems { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all metadataIDs (ExternalIDs) of a given resource. See <see cref="MetadataID{T}"/>.
|
/// Get all metadataIDs (ExternalIDs) of a given resource. See <see cref="MetadataID{T}"/>.
|
||||||
@ -322,6 +330,8 @@ namespace Kyoo
|
|||||||
modelBuilder.Entity<Track>()
|
modelBuilder.Entity<Track>()
|
||||||
.Property(x => x.Slug)
|
.Property(x => x.Slug)
|
||||||
.ValueGeneratedOnAddOrUpdate();
|
.ValueGeneratedOnAddOrUpdate();
|
||||||
|
|
||||||
|
// modelBuilder.Ignore<LibraryItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -74,6 +74,25 @@ namespace Kyoo.Postgresql.Migrations
|
|||||||
migrationBuilder.Sql(@"
|
migrationBuilder.Sql(@"
|
||||||
CREATE TRIGGER show_slug_trigger AFTER UPDATE OF slug ON shows
|
CREATE TRIGGER show_slug_trigger AFTER UPDATE OF slug ON shows
|
||||||
FOR EACH ROW EXECUTE PROCEDURE show_slug_update();");
|
FOR EACH ROW EXECUTE PROCEDURE show_slug_update();");
|
||||||
|
|
||||||
|
|
||||||
|
// language=PostgreSQL
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
CREATE VIEW library_items AS
|
||||||
|
SELECT s.id, s.slug, s.title, s.overview, s.status, s.start_air, s.end_air, s.poster, CASE
|
||||||
|
WHEN s.is_movie THEN 'movie'::item_type
|
||||||
|
ELSE 'show'::item_type
|
||||||
|
END AS type
|
||||||
|
FROM shows AS s
|
||||||
|
WHERE NOT (EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM link_collection_show AS l
|
||||||
|
INNER JOIN collections AS c ON l.first_id = c.id
|
||||||
|
WHERE s.id = l.second_id))
|
||||||
|
UNION ALL
|
||||||
|
SELECT -c0.id, c0.slug, c0.name AS title, c0.overview, 'unknown'::status AS status,
|
||||||
|
NULL AS start_air, NULL AS end_air, c0.poster, 'collection'::item_type AS type
|
||||||
|
FROM collections AS c0");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
@ -90,6 +109,8 @@ namespace Kyoo.Postgresql.Migrations
|
|||||||
migrationBuilder.Sql("DROP TRIGGER episode_slug_trigger ON episodes;");
|
migrationBuilder.Sql("DROP TRIGGER episode_slug_trigger ON episodes;");
|
||||||
// language=PostgreSQL
|
// language=PostgreSQL
|
||||||
migrationBuilder.Sql(@"DROP FUNCTION episode_slug_update;");
|
migrationBuilder.Sql(@"DROP FUNCTION episode_slug_update;");
|
||||||
|
// language=PostgreSQL
|
||||||
|
migrationBuilder.Sql(@"DROP VIEW library_items;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -91,6 +91,10 @@ namespace Kyoo.Postgresql
|
|||||||
modelBuilder.HasPostgresEnum<ItemType>();
|
modelBuilder.HasPostgresEnum<ItemType>();
|
||||||
modelBuilder.HasPostgresEnum<StreamType>();
|
modelBuilder.HasPostgresEnum<StreamType>();
|
||||||
|
|
||||||
|
modelBuilder.Entity<LibraryItem>()
|
||||||
|
.ToView("library_items")
|
||||||
|
.HasKey(x => x.ID);
|
||||||
|
|
||||||
modelBuilder.Entity<User>()
|
modelBuilder.Entity<User>()
|
||||||
.Property(x => x.ExtraData)
|
.Property(x => x.ExtraData)
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
@ -61,6 +61,25 @@ namespace Kyoo.SqLite.Migrations
|
|||||||
END
|
END
|
||||||
WHERE ShowID = new.ID;
|
WHERE ShowID = new.ID;
|
||||||
END;");
|
END;");
|
||||||
|
|
||||||
|
|
||||||
|
// language=SQLite
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
CREATE VIEW LibraryItems AS
|
||||||
|
SELECT s.ID, s.Slug, s.Title, s.Overview, s.Status, s.StartAir, s.EndAir, s.Poster, CASE
|
||||||
|
WHEN s.IsMovie THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS Type
|
||||||
|
FROM Shows AS s
|
||||||
|
WHERE NOT (EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM 'Link<Collection, Show>' AS l
|
||||||
|
INNER JOIN Collections AS c ON l.FirstID = c.ID
|
||||||
|
WHERE s.ID = l.SecondID))
|
||||||
|
UNION ALL
|
||||||
|
SELECT -c0.ID, c0.Slug, c0.Name AS Title, c0.Overview, 3 AS Status,
|
||||||
|
NULL AS StartAir, NULL AS EndAir, c0.Poster, 2 AS Type
|
||||||
|
FROM collections AS c0");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
@ -108,6 +108,10 @@ namespace Kyoo.SqLite
|
|||||||
modelBuilder.Entity<User>()
|
modelBuilder.Entity<User>()
|
||||||
.Property(x => x.ExtraData)
|
.Property(x => x.ExtraData)
|
||||||
.HasConversion(jsonConvertor);
|
.HasConversion(jsonConvertor);
|
||||||
|
|
||||||
|
modelBuilder.Entity<LibraryItem>()
|
||||||
|
.ToView("LibraryItems")
|
||||||
|
.HasKey(x => x.ID);
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,7 @@ namespace Kyoo.Tests
|
|||||||
ShowRepository show = new(_database, studio, people, genre, provider);
|
ShowRepository show = new(_database, studio, people, genre, provider);
|
||||||
SeasonRepository season = new(_database, provider);
|
SeasonRepository season = new(_database, provider);
|
||||||
LibraryItemRepository libraryItem = new(_database,
|
LibraryItemRepository libraryItem = new(_database,
|
||||||
new Lazy<ILibraryRepository>(() => LibraryManager.LibraryRepository),
|
new Lazy<ILibraryRepository>(() => LibraryManager.LibraryRepository));
|
||||||
new Lazy<IShowRepository>(() => LibraryManager.ShowRepository),
|
|
||||||
new Lazy<ICollectionRepository>(() => LibraryManager.CollectionRepository));
|
|
||||||
TrackRepository track = new(_database);
|
TrackRepository track = new(_database);
|
||||||
EpisodeRepository episode = new(_database, provider, track);
|
EpisodeRepository episode = new(_database, provider, track);
|
||||||
|
|
||||||
|
@ -22,15 +22,7 @@ namespace Kyoo.Controllers
|
|||||||
/// A lazy loaded library repository to validate queries (check if a library does exist)
|
/// A lazy loaded library repository to validate queries (check if a library does exist)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Lazy<ILibraryRepository> _libraries;
|
private readonly Lazy<ILibraryRepository> _libraries;
|
||||||
/// <summary>
|
|
||||||
/// A lazy loaded show repository to get a show from it's id.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Lazy<IShowRepository> _shows;
|
|
||||||
/// <summary>
|
|
||||||
/// A lazy loaded collection repository to get a collection from it's id.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Lazy<ICollectionRepository> _collections;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title;
|
protected override Expression<Func<LibraryItem, object>> DefaultSort => x => x.Title;
|
||||||
|
|
||||||
@ -38,60 +30,41 @@ namespace Kyoo.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LibraryItemRepository"/>.
|
/// Create a new <see cref="LibraryItemRepository"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="database">The databse instance</param>
|
/// <param name="database">The database instance</param>
|
||||||
/// <param name="libraries">A lazy loaded library repository</param>
|
/// <param name="libraries">A lazy loaded library repository</param>
|
||||||
/// <param name="shows">A lazy loaded show repository</param>
|
|
||||||
/// <param name="collections">A lazy loaded collection repository</param>
|
|
||||||
public LibraryItemRepository(DatabaseContext database,
|
public LibraryItemRepository(DatabaseContext database,
|
||||||
Lazy<ILibraryRepository> libraries,
|
Lazy<ILibraryRepository> libraries)
|
||||||
Lazy<IShowRepository> shows,
|
|
||||||
Lazy<ICollectionRepository> collections)
|
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_libraries = libraries;
|
_libraries = libraries;
|
||||||
_shows = shows;
|
|
||||||
_collections = collections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<LibraryItem> GetOrDefault(int id)
|
public override Task<LibraryItem> GetOrDefault(int id)
|
||||||
{
|
{
|
||||||
return id > 0
|
return _database.LibraryItems.FirstOrDefaultAsync(x => x.ID == id);
|
||||||
? new LibraryItem(await _shows.Value.GetOrDefault(id))
|
|
||||||
: new LibraryItem(await _collections.Value.GetOrDefault(-id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> GetOrDefault(string slug)
|
public override Task<LibraryItem> GetOrDefault(string slug)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("You can't get a library item by a slug.");
|
return _database.LibraryItems.SingleOrDefaultAsync(x => x.Slug == slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get a basic queryable with the right mapping from shows & collections.
|
|
||||||
/// Shows contained in a collection are excluded.
|
|
||||||
/// </summary>
|
|
||||||
private IQueryable<LibraryItem> ItemsQuery
|
|
||||||
=> _database.Shows
|
|
||||||
.Where(x => !x.Collections.Any())
|
|
||||||
.Select(LibraryItem.FromShow)
|
|
||||||
.Concat(_database.Collections
|
|
||||||
.Select(LibraryItem.FromCollection));
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<ICollection<LibraryItem>> GetAll(Expression<Func<LibraryItem, bool>> where = null,
|
public override Task<ICollection<LibraryItem>> GetAll(Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return ApplyFilters(ItemsQuery, where, sort, limit);
|
return ApplyFilters(_database.LibraryItems, where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<int> GetCount(Expression<Func<LibraryItem, bool>> where = null)
|
public override Task<int> GetCount(Expression<Func<LibraryItem, bool>> where = null)
|
||||||
{
|
{
|
||||||
IQueryable<LibraryItem> query = ItemsQuery;
|
IQueryable<LibraryItem> query = _database.LibraryItems;
|
||||||
if (where != null)
|
if (where != null)
|
||||||
query = query.Where(where);
|
query = query.Where(where);
|
||||||
return query.CountAsync();
|
return query.CountAsync();
|
||||||
@ -100,7 +73,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<LibraryItem>> Search(string query)
|
public override async Task<ICollection<LibraryItem>> Search(string query)
|
||||||
{
|
{
|
||||||
return await ItemsQuery
|
return await _database.LibraryItems
|
||||||
.Where(_database.Like<LibraryItem>(x => x.Title, $"%{query}%"))
|
.Where(_database.Like<LibraryItem>(x => x.Title, $"%{query}%"))
|
||||||
.OrderBy(DefaultSort)
|
.OrderBy(DefaultSort)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
@ -109,7 +82,6 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> Create(LibraryItem obj) => throw new InvalidOperationException();
|
public override Task<LibraryItem> Create(LibraryItem obj) => throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj) => throw new InvalidOperationException();
|
public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj) => throw new InvalidOperationException();
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user