Fix groupings not applied (#14826)

This commit is contained in:
JPVenson
2025-09-23 00:31:21 +03:00
committed by GitHub
parent 162985bb23
commit 98f5e21bb8
2 changed files with 54 additions and 42 deletions

View File

@@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.Library
/// <inheritdoc /> /// <inheritdoc />
public UserItemData? GetUserData(User user, BaseItem item) public UserItemData? GetUserData(User user, BaseItem item)
{ {
return item.UserData.Where(e => e.UserId.Equals(user.Id)).Select(Map).FirstOrDefault() ?? new UserItemData() return item.UserData?.Where(e => e.UserId.Equals(user.Id)).Select(Map).FirstOrDefault() ?? new UserItemData()
{ {
Key = item.GetUserDataKeys()[0], Key = item.GetUserDataKeys()[0],
}; };

View File

@@ -271,7 +271,7 @@ public sealed class BaseItemRepository
result.TotalRecordCount = dbQuery.Count(); result.TotalRecordCount = dbQuery.Count();
} }
dbQuery = ApplyGroupingFilter(dbQuery, filter); dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyQueryPaging(dbQuery, filter); dbQuery = ApplyQueryPaging(dbQuery, filter);
result.Items = dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray(); result.Items = dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray();
@@ -290,7 +290,7 @@ public sealed class BaseItemRepository
dbQuery = TranslateQuery(dbQuery, context, filter); dbQuery = TranslateQuery(dbQuery, context, filter);
dbQuery = ApplyGroupingFilter(dbQuery, filter); dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyQueryPaging(dbQuery, filter); dbQuery = ApplyQueryPaging(dbQuery, filter);
return dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray(); return dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray();
@@ -332,7 +332,7 @@ public sealed class BaseItemRepository
var mainquery = PrepareItemQuery(context, filter); var mainquery = PrepareItemQuery(context, filter);
mainquery = TranslateQuery(mainquery, context, filter); mainquery = TranslateQuery(mainquery, context, filter);
mainquery = mainquery.Where(g => g.DateCreated >= subqueryGrouped.Min(s => s.MaxDateCreated)); mainquery = mainquery.Where(g => g.DateCreated >= subqueryGrouped.Min(s => s.MaxDateCreated));
mainquery = ApplyGroupingFilter(mainquery, filter); mainquery = ApplyGroupingFilter(context, mainquery, filter);
mainquery = ApplyQueryPaging(mainquery, filter); mainquery = ApplyQueryPaging(mainquery, filter);
return mainquery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray(); return mainquery.AsEnumerable().Where(e => e is not null).Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)).ToArray();
@@ -369,36 +369,50 @@ public sealed class BaseItemRepository
return query.ToArray(); return query.ToArray();
} }
private IQueryable<BaseItemEntity> ApplyGroupingFilter(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter) private IQueryable<BaseItemEntity> ApplyGroupingFilter(JellyfinDbContext context, IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
{ {
// This whole block is needed to filter duplicate entries on request // This whole block is needed to filter duplicate entries on request
// for the time being it cannot be used because it would destroy the ordering // for the time being it cannot be used because it would destroy the ordering
// this results in "duplicate" responses for queries that try to lookup individual series or multiple versions but // this results in "duplicate" responses for queries that try to lookup individual series or multiple versions but
// for that case the invoker has to run a DistinctBy(e => e.PresentationUniqueKey) on their own // for that case the invoker has to run a DistinctBy(e => e.PresentationUniqueKey) on their own
// var enableGroupByPresentationUniqueKey = EnableGroupByPresentationUniqueKey(filter); var enableGroupByPresentationUniqueKey = EnableGroupByPresentationUniqueKey(filter);
// if (enableGroupByPresentationUniqueKey && filter.GroupBySeriesPresentationUniqueKey) if (enableGroupByPresentationUniqueKey && filter.GroupBySeriesPresentationUniqueKey)
// { {
// dbQuery = ApplyOrder(dbQuery, filter); var tempQuery = dbQuery.GroupBy(e => new { e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }).Select(e => e.FirstOrDefault()).Select(e => e!.Id);
// dbQuery = dbQuery.GroupBy(e => new { e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }).Select(e => e.First()); dbQuery = context.BaseItems.Where(e => tempQuery.Contains(e.Id));
// } dbQuery = ApplyOrder(dbQuery, filter);
// else if (enableGroupByPresentationUniqueKey) }
// { else if (enableGroupByPresentationUniqueKey)
// dbQuery = ApplyOrder(dbQuery, filter); {
// dbQuery = dbQuery.GroupBy(e => e.PresentationUniqueKey).Select(e => e.First()); var tempQuery = dbQuery.GroupBy(e => e.PresentationUniqueKey).Select(e => e.FirstOrDefault()).Select(e => e!.Id);
// } dbQuery = context.BaseItems.Where(e => tempQuery.Contains(e.Id));
// else if (filter.GroupBySeriesPresentationUniqueKey) dbQuery = ApplyOrder(dbQuery, filter);
// { }
// dbQuery = ApplyOrder(dbQuery, filter); else if (filter.GroupBySeriesPresentationUniqueKey)
// dbQuery = dbQuery.GroupBy(e => e.SeriesPresentationUniqueKey).Select(e => e.First()); {
// } var tempQuery = dbQuery.GroupBy(e => e.SeriesPresentationUniqueKey).Select(e => e.FirstOrDefault()).Select(e => e!.Id);
// else dbQuery = context.BaseItems.Where(e => tempQuery.Contains(e.Id));
// { dbQuery = ApplyOrder(dbQuery, filter);
// dbQuery = dbQuery.Distinct(); }
// dbQuery = ApplyOrder(dbQuery, filter); else
// } {
dbQuery = dbQuery.Distinct(); dbQuery = dbQuery.Distinct();
dbQuery = ApplyOrder(dbQuery, filter); dbQuery = ApplyOrder(dbQuery, filter);
}
dbQuery = dbQuery.Include(e => e.TrailerTypes)
.Include(e => e.Provider)
.Include(e => e.LockedFields)
.Include(e => e.UserData);
if (filter.DtoOptions.EnableImages)
{
dbQuery = dbQuery.Include(e => e.Images);
}
// dbQuery = dbQuery.Distinct();
// dbQuery = ApplyOrder(dbQuery, filter);
return dbQuery; return dbQuery;
} }
@@ -426,8 +440,8 @@ public sealed class BaseItemRepository
private IQueryable<BaseItemEntity> ApplyQueryFilter(IQueryable<BaseItemEntity> dbQuery, JellyfinDbContext context, InternalItemsQuery filter) private IQueryable<BaseItemEntity> ApplyQueryFilter(IQueryable<BaseItemEntity> dbQuery, JellyfinDbContext context, InternalItemsQuery filter)
{ {
dbQuery = TranslateQuery(dbQuery, context, filter); dbQuery = TranslateQuery(dbQuery, context, filter);
dbQuery = ApplyOrder(dbQuery, filter); // dbQuery = ApplyOrder(dbQuery, filter);
dbQuery = ApplyGroupingFilter(dbQuery, filter); dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyQueryPaging(dbQuery, filter); dbQuery = ApplyQueryPaging(dbQuery, filter);
return dbQuery; return dbQuery;
} }
@@ -435,16 +449,7 @@ public sealed class BaseItemRepository
private IQueryable<BaseItemEntity> PrepareItemQuery(JellyfinDbContext context, InternalItemsQuery filter) private IQueryable<BaseItemEntity> PrepareItemQuery(JellyfinDbContext context, InternalItemsQuery filter)
{ {
IQueryable<BaseItemEntity> dbQuery = context.BaseItems.AsNoTracking(); IQueryable<BaseItemEntity> dbQuery = context.BaseItems.AsNoTracking();
dbQuery = dbQuery.AsSingleQuery() dbQuery = dbQuery.AsSingleQuery();
.Include(e => e.TrailerTypes)
.Include(e => e.Provider)
.Include(e => e.LockedFields)
.Include(e => e.UserData);
if (filter.DtoOptions.EnableImages)
{
dbQuery = dbQuery.Include(e => e.Images);
}
return dbQuery; return dbQuery;
} }
@@ -729,13 +734,20 @@ public sealed class BaseItemRepository
} }
using var context = _dbProvider.CreateDbContext(); using var context = _dbProvider.CreateDbContext();
var item = PrepareItemQuery(context, new() var dbQuery = PrepareItemQuery(context, new()
{ {
DtoOptions = new() DtoOptions = new()
{ {
EnableImages = true EnableImages = true
} }
}).FirstOrDefault(e => e.Id == id); });
dbQuery = dbQuery.Include(e => e.TrailerTypes)
.Include(e => e.Provider)
.Include(e => e.LockedFields)
.Include(e => e.UserData)
.Include(e => e.Images);
var item = dbQuery.FirstOrDefault(e => e.Id == id);
if (item is null) if (item is null)
{ {
return null; return null;