Fix AdjacentTo being ignored on non-recursive item queries
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1085,15 +1085,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
items = ApplyNameFilter(items, query);
|
||||
}
|
||||
|
||||
var filteredItems = items as IReadOnlyList<BaseItem> ?? items.ToList();
|
||||
var result = UserViewBuilder.SortAndPage(filteredItems, null, query, LibraryManager);
|
||||
|
||||
if (query.EnableTotalRecordCount)
|
||||
{
|
||||
result.TotalRecordCount = filteredItems.Count;
|
||||
}
|
||||
|
||||
return result;
|
||||
return UserViewBuilder.SortAndPage(items, null, query, LibraryManager);
|
||||
}
|
||||
|
||||
private static IEnumerable<BaseItem> ApplyNameFilter(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
||||
|
||||
@@ -490,6 +490,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();
|
||||
|
||||
// Adjacency is defined by the order the query asked for, so it has to run after sorting but before paging.
|
||||
if (!query.AdjacentTo.IsNullOrEmpty())
|
||||
{
|
||||
itemsArray = FilterForAdjacency(itemsArray, query.AdjacentTo.Value).ToArray();
|
||||
}
|
||||
|
||||
var totalCount = itemsArray.Length;
|
||||
|
||||
if (query.Limit.HasValue && query.Limit.Value > 0)
|
||||
@@ -886,26 +893,32 @@ namespace MediaBrowser.Controller.Entities
|
||||
return _userViewManager.GetUserSubView(parent.Id, type, localizationKey, sortName);
|
||||
}
|
||||
|
||||
public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, Guid adjacentTo)
|
||||
/// <summary>
|
||||
/// Trims an ordered list down to the requested item and its immediate neighbours.
|
||||
/// </summary>
|
||||
/// <param name="list">The items in the order the query returned them.</param>
|
||||
/// <param name="adjacentTo">The id of the item to return the neighbours of.</param>
|
||||
/// <returns>The previous item, the requested item and the next item, in order.</returns>
|
||||
public static IEnumerable<BaseItem> FilterForAdjacency(IReadOnlyList<BaseItem> list, Guid adjacentTo)
|
||||
{
|
||||
var adjacentToItem = list.FirstOrDefault(i => i.Id.Equals(adjacentTo));
|
||||
|
||||
var index = list.IndexOf(adjacentToItem);
|
||||
|
||||
var previousId = Guid.Empty;
|
||||
var nextId = Guid.Empty;
|
||||
|
||||
if (index > 0)
|
||||
var index = -1;
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
previousId = list[index - 1].Id;
|
||||
if (list[i].Id.Equals(adjacentTo))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < list.Count - 1)
|
||||
// The item isn't part of this result set, so it has no neighbours in it either.
|
||||
if (index < 0)
|
||||
{
|
||||
nextId = list[index + 1].Id;
|
||||
return [];
|
||||
}
|
||||
|
||||
return list.Where(i => i.Id.Equals(previousId) || i.Id.Equals(nextId) || i.Id.Equals(adjacentTo));
|
||||
var start = Math.Max(index - 1, 0);
|
||||
return list.Skip(start).Take(Math.Min(index + 2, list.Count) - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user