Collection Rework (#2830)
This commit is contained in:
parent
0dacc061f1
commit
deaaccb96a
93 changed files with 5413 additions and 1120 deletions
|
|
@ -0,0 +1,76 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using API.Data.Misc;
|
||||
using API.Data.Repositories;
|
||||
using API.Entities;
|
||||
using API.Entities.Metadata;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Extensions.QueryExtensions.Filtering;
|
||||
|
||||
public static class SearchQueryableExtensions
|
||||
{
|
||||
public static IQueryable<AppUserCollection> Search(this IQueryable<AppUserCollection> queryable,
|
||||
string searchQuery, int userId, AgeRestriction userRating)
|
||||
{
|
||||
return queryable
|
||||
.Where(uc => uc.Promoted || uc.AppUserId == userId)
|
||||
.Where(s => EF.Functions.Like(s.Title!, $"%{searchQuery}%")
|
||||
|| EF.Functions.Like(s.NormalizedTitle!, $"%{searchQuery}%"))
|
||||
.RestrictAgainstAgeRestriction(userRating)
|
||||
.OrderBy(s => s.NormalizedTitle);
|
||||
}
|
||||
|
||||
public static IQueryable<ReadingList> Search(this IQueryable<ReadingList> queryable,
|
||||
string searchQuery, int userId, AgeRestriction userRating)
|
||||
{
|
||||
return queryable
|
||||
.Where(rl => rl.AppUserId == userId || rl.Promoted)
|
||||
.Where(rl => EF.Functions.Like(rl.Title, $"%{searchQuery}%"))
|
||||
.RestrictAgainstAgeRestriction(userRating)
|
||||
.OrderBy(s => s.NormalizedTitle);
|
||||
}
|
||||
|
||||
public static IQueryable<Library> Search(this IQueryable<Library> queryable,
|
||||
string searchQuery, int userId, IEnumerable<int> libraryIds)
|
||||
{
|
||||
return queryable
|
||||
.Where(l => libraryIds.Contains(l.Id))
|
||||
.Where(l => EF.Functions.Like(l.Name, $"%{searchQuery}%"))
|
||||
.IsRestricted(QueryContext.Search)
|
||||
.AsSplitQuery()
|
||||
.OrderBy(l => l.Name.ToLower());
|
||||
}
|
||||
|
||||
public static IQueryable<Person> SearchPeople(this IQueryable<SeriesMetadata> queryable,
|
||||
string searchQuery, IEnumerable<int> seriesIds)
|
||||
{
|
||||
return queryable
|
||||
.Where(sm => seriesIds.Contains(sm.SeriesId))
|
||||
.SelectMany(sm => sm.People.Where(t => t.Name != null && EF.Functions.Like(t.Name, $"%{searchQuery}%")))
|
||||
.AsSplitQuery()
|
||||
.Distinct()
|
||||
.OrderBy(p => p.NormalizedName);
|
||||
}
|
||||
|
||||
public static IQueryable<Genre> SearchGenres(this IQueryable<SeriesMetadata> queryable,
|
||||
string searchQuery, IEnumerable<int> seriesIds)
|
||||
{
|
||||
return queryable
|
||||
.Where(sm => seriesIds.Contains(sm.SeriesId))
|
||||
.SelectMany(sm => sm.Genres.Where(t => EF.Functions.Like(t.Title, $"%{searchQuery}%")))
|
||||
.Distinct()
|
||||
.OrderBy(t => t.NormalizedTitle);
|
||||
}
|
||||
|
||||
public static IQueryable<Tag> SearchTags(this IQueryable<SeriesMetadata> queryable,
|
||||
string searchQuery, IEnumerable<int> seriesIds)
|
||||
{
|
||||
return queryable
|
||||
.Where(sm => seriesIds.Contains(sm.SeriesId))
|
||||
.SelectMany(sm => sm.Tags.Where(t => EF.Functions.Like(t.Title, $"%{searchQuery}%")))
|
||||
.AsSplitQuery()
|
||||
.Distinct()
|
||||
.OrderBy(t => t.NormalizedTitle);
|
||||
}
|
||||
}
|
||||
|
|
@ -551,25 +551,26 @@ public static class SeriesFilter
|
|||
}
|
||||
|
||||
public static IQueryable<Series> HasCollectionTags(this IQueryable<Series> queryable, bool condition,
|
||||
FilterComparison comparison, IList<int> collectionTags)
|
||||
FilterComparison comparison, IList<int> collectionTags, IList<int> collectionSeries)
|
||||
{
|
||||
if (!condition || collectionTags.Count == 0) return queryable;
|
||||
|
||||
|
||||
switch (comparison)
|
||||
{
|
||||
case FilterComparison.Equal:
|
||||
case FilterComparison.Contains:
|
||||
return queryable.Where(s => s.Metadata.CollectionTags.Any(t => collectionTags.Contains(t.Id)));
|
||||
return queryable.Where(s => collectionSeries.Contains(s.Id));
|
||||
case FilterComparison.NotContains:
|
||||
case FilterComparison.NotEqual:
|
||||
return queryable.Where(s => !s.Metadata.CollectionTags.Any(t => collectionTags.Contains(t.Id)));
|
||||
return queryable.Where(s => !collectionSeries.Contains(s.Id));
|
||||
case FilterComparison.MustContains:
|
||||
// Deconstruct and do a Union of a bunch of where statements since this doesn't translate
|
||||
// // Deconstruct and do a Union of a bunch of where statements since this doesn't translate
|
||||
var queries = new List<IQueryable<Series>>()
|
||||
{
|
||||
queryable
|
||||
};
|
||||
queries.AddRange(collectionTags.Select(gId => queryable.Where(s => s.Metadata.CollectionTags.Any(p => p.Id == gId))));
|
||||
queries.AddRange(collectionSeries.Select(gId => queryable.Where(s => collectionSeries.Any(p => p == s.Id))));
|
||||
|
||||
return queries.Aggregate((q1, q2) => q1.Intersect(q2));
|
||||
case FilterComparison.GreaterThan:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,23 @@ public static class IncludesExtensions
|
|||
queryable = queryable.Include(c => c.SeriesMetadatas);
|
||||
}
|
||||
|
||||
if (includes.HasFlag(CollectionTagIncludes.SeriesMetadataWithSeries))
|
||||
{
|
||||
queryable = queryable.Include(c => c.SeriesMetadatas).ThenInclude(s => s.Series);
|
||||
}
|
||||
|
||||
return queryable.AsSplitQuery();
|
||||
}
|
||||
|
||||
public static IQueryable<AppUserCollection> Includes(this IQueryable<AppUserCollection> queryable,
|
||||
CollectionIncludes includes)
|
||||
{
|
||||
if (includes.HasFlag(CollectionIncludes.Series))
|
||||
{
|
||||
queryable = queryable.Include(c => c.Items);
|
||||
}
|
||||
|
||||
|
||||
return queryable.AsSplitQuery();
|
||||
}
|
||||
|
||||
|
|
@ -206,6 +223,12 @@ public static class IncludesExtensions
|
|||
query = query.Include(u => u.ExternalSources);
|
||||
}
|
||||
|
||||
if (includeFlags.HasFlag(AppUserIncludes.Collections))
|
||||
{
|
||||
query = query.Include(u => u.Collections)
|
||||
.ThenInclude(c => c.Items);
|
||||
}
|
||||
|
||||
return query.AsSplitQuery();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using API.Data.Misc;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
|
@ -24,6 +25,7 @@ public static class RestrictByAgeExtensions
|
|||
return q;
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static IQueryable<CollectionTag> RestrictAgainstAgeRestriction(this IQueryable<CollectionTag> queryable, AgeRestriction restriction)
|
||||
{
|
||||
if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
|
||||
|
|
@ -38,6 +40,20 @@ public static class RestrictByAgeExtensions
|
|||
sm.AgeRating <= restriction.AgeRating && sm.AgeRating > AgeRating.Unknown));
|
||||
}
|
||||
|
||||
public static IQueryable<AppUserCollection> RestrictAgainstAgeRestriction(this IQueryable<AppUserCollection> queryable, AgeRestriction restriction)
|
||||
{
|
||||
if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
|
||||
|
||||
if (restriction.IncludeUnknowns)
|
||||
{
|
||||
return queryable.Where(c => c.Items.All(sm =>
|
||||
sm.Metadata.AgeRating <= restriction.AgeRating));
|
||||
}
|
||||
|
||||
return queryable.Where(c => c.Items.All(sm =>
|
||||
sm.Metadata.AgeRating <= restriction.AgeRating && sm.Metadata.AgeRating > AgeRating.Unknown));
|
||||
}
|
||||
|
||||
public static IQueryable<Genre> RestrictAgainstAgeRestriction(this IQueryable<Genre> queryable, AgeRestriction restriction)
|
||||
{
|
||||
if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue