aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-04-26 17:55:19 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-04-26 18:53:06 +0200
commitfc866a64e063c9f04df3fab9a00846501c8d2b13 (patch)
tree2d3b040ad903dc0c4205658831c5f66939b1a504 /Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
parentf806ae40187ff5d853fff7cdd72709eab39bc9ac (diff)
Remove unnecessary materializations
Diffstat (limited to 'Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs')
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs18
1 files changed, 7 insertions, 11 deletions
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
index 907d8527aa..c4464008d4 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
@@ -133,8 +133,9 @@ public sealed partial class BaseItemRepository
IsSeries = filter.IsSeries
});
- // Materialize the matching CleanValues early. This splits one massive expression tree
- // into two simpler queries, dramatically reducing EF Core expression compilation time.
+ // Keep this as an IQueryable sub-select. Materializing to a list would inline one
+ // bound parameter per CleanValue and hit SQLite's variable cap on libraries with
+ // high-cardinality value types (e.g. tens of thousands of artists).
var matchingCleanValues = context.ItemValuesMap
.Where(ivm => itemValueTypes.Contains(ivm.ItemValue.Type))
.Join(
@@ -142,8 +143,7 @@ public sealed partial class BaseItemRepository
ivm => ivm.ItemId,
g => g.Id,
(ivm, g) => ivm.ItemValue.CleanValue)
- .Distinct()
- .ToList();
+ .Distinct();
var innerQuery = PrepareItemQuery(context, filter)
.Where(e => e.Type == returnType)
@@ -170,10 +170,8 @@ public sealed partial class BaseItemRepository
ExcludeItemIds = filter.ExcludeItemIds
};
- // Materialize the matching IDs first. This keeps the complex nested subquery
- // (inner filter + ItemValues join + search + GroupBy) as a single simple SQL statement,
- // and then the entity load with Includes uses a flat WHERE Id IN (...) list.
- // This avoids EF having to compile the entire nested expression tree into the final query.
+ // Build the master query and collapse rows that share a PresentationUniqueKey
+ // (e.g. alternate versions) by picking the lowest Id per group.
var masterQuery = TranslateQuery(innerQuery, context, outerQueryFilter);
var orderedMasterQuery = ApplyOrder(masterQuery, filter, context)
@@ -229,9 +227,7 @@ public sealed partial class BaseItemRepository
var musicArtistTypeName = _itemTypeLookup.BaseItemKindNames[BaseItemKind.MusicArtist];
var audioTypeName = _itemTypeLookup.BaseItemKindNames[BaseItemKind.Audio];
var trailerTypeName = _itemTypeLookup.BaseItemKindNames[BaseItemKind.Trailer];
-
- // Materialize the matching IDs to avoid nested subquery in the counts expression tree.
- var itemIds = itemCountQuery.Select(e => e.Id).ToList();
+ var itemIds = itemCountQuery.Select(e => e.Id);
// Rewrite query to avoid SelectMany on navigation properties (which requires SQL APPLY, not supported on SQLite)
// Instead, start from ItemValueMaps and join with BaseItems