Fix AdjacentTo being ignored on non-recursive item queries

This commit is contained in:
Shadowghost
2026-07-29 13:13:44 +02:00
parent afb716566d
commit d8fc0a9914
5 changed files with 58 additions and 49 deletions
@@ -35,11 +35,40 @@ public sealed partial class BaseItemRepository
{
dbQuery = TranslateQuery(dbQuery, context, filter);
dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyAdjacencyFilter(context, dbQuery, filter);
dbQuery = ApplyQueryPaging(dbQuery, filter);
dbQuery = ApplyNavigations(dbQuery, filter);
return dbQuery;
}
/// <summary>
/// Trims an ordered query down to the AdjacentTo item and its immediate neighbours.
/// </summary>
private IQueryable<BaseItemEntity> ApplyAdjacencyFilter(JellyfinDbContext context, IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
{
if (filter.AdjacentTo.IsNullOrEmpty())
{
return dbQuery;
}
// Adjacency is relative to the result set and the order the query asked for, so the ids have
// to be read back in that order.
var orderedIds = dbQuery.Select(e => e.Id).ToList();
var index = orderedIds.IndexOf(filter.AdjacentTo.Value);
if (index < 0)
{
// The item isn't part of this result set, so it has no neighbours in it either.
return dbQuery.Take(0);
}
var start = Math.Max(index - 1, 0);
var adjacentIds = orderedIds.GetRange(start, Math.Min(index + 2, orderedIds.Count) - start);
var adjacentQuery = context.BaseItems.AsNoTracking().AsSingleQuery().Where(e => adjacentIds.Contains(e.Id));
return ApplyOrder(adjacentQuery, filter, context);
}
private IQueryable<BaseItemEntity> ApplyQueryPaging(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
{
if (filter.Limit.HasValue || filter.StartIndex.HasValue)
@@ -49,6 +49,7 @@ public sealed partial class BaseItemRepository
dbQuery = TranslateQuery(dbQuery, context, filter);
dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyAdjacencyFilter(context, dbQuery, filter);
if (filter.EnableTotalRecordCount)
{
@@ -75,6 +76,7 @@ public sealed partial class BaseItemRepository
dbQuery = TranslateQuery(dbQuery, context, filter);
dbQuery = ApplyGroupingFilter(context, dbQuery, filter);
dbQuery = ApplyAdjacencyFilter(context, dbQuery, filter);
dbQuery = ApplyQueryPaging(dbQuery, filter);
var hasRandomSort = filter.OrderBy.Any(e => e.OrderBy == ItemSortBy.Random);
@@ -1243,33 +1243,6 @@ public sealed partial class BaseItemRepository
}
}
if (filter.AdjacentTo.HasValue && !filter.AdjacentTo.Value.IsEmpty())
{
var adjacentToId = filter.AdjacentTo.Value;
var targetItem = context.BaseItems.Where(e => e.Id == adjacentToId).Select(e => new { e.SortName, e.Id }).FirstOrDefault();
if (targetItem is not null)
{
var targetSortName = targetItem.SortName ?? string.Empty;
// Fetch both prev and next adjacent items in a single query using Concat (UNION ALL).
var adjacentIds = context.BaseItems
.Where(e => string.Compare(e.SortName, targetSortName) < 0)
.OrderByDescending(e => e.SortName)
.Select(e => e.Id)
.Take(1)
.Concat(
context.BaseItems
.Where(e => string.Compare(e.SortName, targetSortName) > 0)
.OrderBy(e => e.SortName)
.Select(e => e.Id)
.Take(1))
.ToList();
adjacentIds.Add(adjacentToId);
baseQuery = baseQuery.Where(e => adjacentIds.Contains(e.Id));
}
}
return baseQuery;
}
}