Browse Source

Fix contributing artist query (#14991)

theguymadmax 6 days ago
parent
commit
794e1361d7

+ 13 - 2
Jellyfin.Server.Implementations/Item/BaseItemRepository.cs

@@ -2014,7 +2014,7 @@ public sealed class BaseItemRepository
 
 
         if (filter.ArtistIds.Length > 0)
         if (filter.ArtistIds.Length > 0)
         {
         {
-            baseQuery = baseQuery.WhereReferencedItem(context, ItemValueType.Artist, filter.ArtistIds);
+            baseQuery = baseQuery.WhereReferencedItemMultipleTypes(context, [ItemValueType.Artist, ItemValueType.AlbumArtist], filter.ArtistIds);
         }
         }
 
 
         if (filter.AlbumArtistIds.Length > 0)
         if (filter.AlbumArtistIds.Length > 0)
@@ -2024,7 +2024,18 @@ public sealed class BaseItemRepository
 
 
         if (filter.ContributingArtistIds.Length > 0)
         if (filter.ContributingArtistIds.Length > 0)
         {
         {
-            baseQuery = baseQuery.WhereReferencedItem(context, ItemValueType.Artist, filter.ContributingArtistIds);
+            var contributingNames = context.BaseItems
+                .Where(b => filter.ContributingArtistIds.Contains(b.Id))
+                .Select(b => b.CleanName);
+
+            baseQuery = baseQuery.Where(e =>
+                e.ItemValues!.Any(ivm =>
+                    ivm.ItemValue.Type == ItemValueType.Artist &&
+                    contributingNames.Contains(ivm.ItemValue.CleanValue))
+                &&
+                !e.ItemValues!.Any(ivm =>
+                    ivm.ItemValue.Type == ItemValueType.AlbumArtist &&
+                    contributingNames.Contains(ivm.ItemValue.CleanValue)));
         }
         }
 
 
         if (filter.AlbumIds.Length > 0)
         if (filter.AlbumIds.Length > 0)

+ 27 - 0
src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinQueryHelperExtensions.cs

@@ -53,6 +53,33 @@ public static class JellyfinQueryHelperExtensions
         return baseQuery.Where(ReferencedItemFilterExpressionBuilder(context, itemValueType, referenceIds, invert));
         return baseQuery.Where(ReferencedItemFilterExpressionBuilder(context, itemValueType, referenceIds, invert));
     }
     }
 
 
+    /// <summary>
+    /// Builds a query that checks referenced ItemValues for a cross BaseItem lookup.
+    /// </summary>
+    /// <param name="baseQuery">The source query.</param>
+    /// <param name="context">The database context.</param>
+    /// <param name="itemValueTypes">The type of item value to reference.</param>
+    /// <param name="referenceIds">The list of BaseItem ids to check matches.</param>
+    /// <param name="invert">If set an exclusion check is performed instead.</param>
+    /// <returns>A Query.</returns>
+    public static IQueryable<BaseItemEntity> WhereReferencedItemMultipleTypes(
+        this IQueryable<BaseItemEntity> baseQuery,
+        JellyfinDbContext context,
+        IList<ItemValueType> itemValueTypes,
+        IList<Guid> referenceIds,
+        bool invert = false)
+    {
+        var itemFilter = OneOrManyExpressionBuilder<BaseItemEntity, Guid>(referenceIds, f => f.Id);
+
+        return baseQuery.Where(item =>
+            context.ItemValues
+                .Join(context.ItemValuesMap, e => e.ItemValueId, e => e.ItemValueId, (itemVal, map) => new { itemVal, map })
+                .Any(val =>
+                    itemValueTypes.Contains(val.itemVal.Type)
+                    && context.BaseItems.Where(itemFilter).Any(e => e.CleanName == val.itemVal.CleanValue)
+                    && val.map.ItemId == item.Id) == EF.Constant(!invert));
+    }
+
     /// <summary>
     /// <summary>
     /// Builds a query expression that checks referenced ItemValues for a cross BaseItem lookup.
     /// Builds a query expression that checks referenced ItemValues for a cross BaseItem lookup.
     /// </summary>
     /// </summary>