Fix favorite filter performance
This commit is contained in:
@@ -168,21 +168,16 @@ public sealed partial class BaseItemRepository
|
||||
IsSeries = filter.IsSeries
|
||||
});
|
||||
|
||||
// Resolve, then materialize, the set of clean values belonging to items that match the inner filter.
|
||||
var matchingCleanValues = context.ItemValuesMap
|
||||
.Where(ivm => itemValueTypes.Contains(ivm.ItemValue.Type))
|
||||
.Join(
|
||||
innerQueryFilter,
|
||||
ivm => ivm.ItemId,
|
||||
g => g.Id,
|
||||
(ivm, g) => ivm.ItemValue.CleanValue)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
// Match CleanName against the resolved clean values.
|
||||
var innerQuery = PrepareItemQuery(context, filter)
|
||||
.Where(e => e.Type == returnType)
|
||||
.WhereOneOrMany(matchingCleanValues, e => e.CleanName!);
|
||||
.Where(e => context.ItemValuesMap
|
||||
.Where(ivm => itemValueTypes.Contains(ivm.ItemValue.Type) && ivm.ItemValue.CleanValue == e.CleanName)
|
||||
.Join(
|
||||
innerQueryFilter,
|
||||
ivm => ivm.ItemId,
|
||||
g => g.Id,
|
||||
(ivm, g) => ivm.ItemId)
|
||||
.Any());
|
||||
|
||||
var outerQueryFilter = new InternalItemsQuery(filter.User)
|
||||
{
|
||||
|
||||
@@ -434,20 +434,34 @@ public sealed partial class BaseItemRepository
|
||||
|
||||
if (filter.IsLiked.HasValue)
|
||||
{
|
||||
var isLiked = filter.IsLiked.Value;
|
||||
baseQuery = baseQuery.Where(e => e.UserData!.Any(ud => ud.UserId == filter.User!.Id && ud.Rating >= UserItemData.MinLikeValue) == isLiked);
|
||||
var likedIds = context.UserData
|
||||
.Where(ud => ud.UserId == filter.User!.Id && ud.Rating >= UserItemData.MinLikeValue)
|
||||
.Select(ud => ud.ItemId);
|
||||
|
||||
baseQuery = filter.IsLiked.Value
|
||||
? baseQuery.Where(e => likedIds.Contains(e.Id))
|
||||
: baseQuery.Where(e => !likedIds.Contains(e.Id));
|
||||
}
|
||||
|
||||
if (filter.IsFavoriteOrLiked.HasValue)
|
||||
if (filter.IsFavoriteOrLiked.HasValue || filter.IsFavorite.HasValue)
|
||||
{
|
||||
var isFavoriteOrLiked = filter.IsFavoriteOrLiked.Value;
|
||||
baseQuery = baseQuery.Where(e => e.UserData!.Any(ud => ud.UserId == filter.User!.Id && ud.IsFavorite) == isFavoriteOrLiked);
|
||||
}
|
||||
var favoriteIds = context.UserData
|
||||
.Where(ud => ud.UserId == filter.User!.Id && ud.IsFavorite)
|
||||
.Select(ud => ud.ItemId);
|
||||
|
||||
if (filter.IsFavorite.HasValue)
|
||||
{
|
||||
var isFavorite = filter.IsFavorite.Value;
|
||||
baseQuery = baseQuery.Where(e => e.UserData!.Any(ud => ud.UserId == filter.User!.Id && ud.IsFavorite) == isFavorite);
|
||||
if (filter.IsFavoriteOrLiked.HasValue)
|
||||
{
|
||||
baseQuery = filter.IsFavoriteOrLiked.Value
|
||||
? baseQuery.Where(e => favoriteIds.Contains(e.Id))
|
||||
: baseQuery.Where(e => !favoriteIds.Contains(e.Id));
|
||||
}
|
||||
|
||||
if (filter.IsFavorite.HasValue)
|
||||
{
|
||||
baseQuery = filter.IsFavorite.Value
|
||||
? baseQuery.Where(e => favoriteIds.Contains(e.Id))
|
||||
: baseQuery.Where(e => !favoriteIds.Contains(e.Id));
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.IsPlayed.HasValue)
|
||||
|
||||
+5
-2
@@ -61,8 +61,11 @@ public class BaseItemConfiguration : IEntityTypeConfiguration<BaseItemEntity>
|
||||
builder.HasIndex(e => new { e.TopParentId, e.MediaType, e.IsVirtualItem, e.DateCreated });
|
||||
// resume
|
||||
builder.HasIndex(e => new { e.MediaType, e.TopParentId, e.IsVirtualItem, e.PresentationUniqueKey });
|
||||
// alternate versions of an item, e.g. resolving the played date of a version onto its primary
|
||||
builder.HasIndex(e => e.PrimaryVersionId);
|
||||
// alternate versions of an item, e.g. resolving the played date of a version onto its primary.
|
||||
// Filtered: almost no item has a primary version, and an index covering those rows too would tempt
|
||||
// the planner into serving "PrimaryVersionId IS NULL" - true for the whole library - out of it.
|
||||
builder.HasIndex(e => e.PrimaryVersionId)
|
||||
.HasFilter("\"PrimaryVersionId\" IS NOT NULL");
|
||||
// sorted library queries (e.g., Series sorted by SortName)
|
||||
builder.HasIndex(e => new { e.Type, e.TopParentId, e.SortName });
|
||||
// NextUp: per-series episode ordering (index seek + range scan on season/episode)
|
||||
|
||||
+2
-1
@@ -376,7 +376,8 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasIndex("PresentationUniqueKey");
|
||||
|
||||
b.HasIndex("PrimaryVersionId");
|
||||
b.HasIndex("PrimaryVersionId")
|
||||
.HasFilter("\"PrimaryVersionId\" IS NOT NULL");
|
||||
|
||||
b.HasIndex("SeasonId");
|
||||
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BaseItems_PrimaryVersionId",
|
||||
table: "BaseItems",
|
||||
column: "PrimaryVersionId");
|
||||
column: "PrimaryVersionId",
|
||||
filter: "\"PrimaryVersionId\" IS NOT NULL");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
+2
-1
@@ -373,7 +373,8 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasIndex("PresentationUniqueKey");
|
||||
|
||||
b.HasIndex("PrimaryVersionId");
|
||||
b.HasIndex("PrimaryVersionId")
|
||||
.HasFilter("\"PrimaryVersionId\" IS NOT NULL");
|
||||
|
||||
b.HasIndex("SeasonId");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user