Add filter to meilisearch in backend

This commit is contained in:
Scott Merchant 2024-06-09 17:08:10 +09:30
parent 71b5a04027
commit e7099c9c19
4 changed files with 42 additions and 7 deletions

View File

@ -38,6 +38,7 @@ public interface ISearchManager
public Task<SearchPage<ILibraryItem>.SearchResult> SearchItems(
string? query,
Sort<ILibraryItem> sortBy,
Filter<ILibraryItem>? filter,
SearchPagination pagination,
Include<ILibraryItem>? include = default
);
@ -98,6 +99,7 @@ public interface ISearchManager
public Task<SearchPage<Episode>.SearchResult> SearchEpisodes(
string? query,
Sort<Episode> sortBy,
Filter<Episode>? filter,
SearchPagination pagination,
Include<Episode>? include = default
);
@ -113,6 +115,7 @@ public interface ISearchManager
public Task<SearchPage<Studio>.SearchResult> SearchStudios(
string? query,
Sort<Studio> sortBy,
Filter<Studio>? filter,
SearchPagination pagination,
Include<Studio>? include = default
);

View File

@ -44,7 +44,7 @@ public class SearchApi : BaseApi
_searchManager = searchManager;
}
// TODO: add filters and facets
// TODO: add facets
/// <summary>
/// Search collections
@ -143,11 +143,12 @@ public class SearchApi : BaseApi
public async Task<SearchPage<ILibraryItem>> SearchItems(
[FromQuery] string? q,
[FromQuery] Sort<ILibraryItem> sortBy,
[FromQuery] Filter<ILibraryItem>? filter,
[FromQuery] SearchPagination pagination,
[FromQuery] Include<ILibraryItem> fields
)
{
return SearchPage(await _searchManager.SearchItems(q, sortBy, pagination, fields));
return SearchPage(await _searchManager.SearchItems(q, sortBy, filter, pagination, fields));
}
/// <summary>
@ -169,11 +170,12 @@ public class SearchApi : BaseApi
public async Task<SearchPage<Episode>> SearchEpisodes(
[FromQuery] string? q,
[FromQuery] Sort<Episode> sortBy,
[FromQuery] Filter<Episode>? filter,
[FromQuery] SearchPagination pagination,
[FromQuery] Include<Episode> fields
)
{
return SearchPage(await _searchManager.SearchEpisodes(q, sortBy, pagination, fields));
return SearchPage(await _searchManager.SearchEpisodes(q, sortBy, filter, pagination, fields));
}
/// <summary>
@ -195,10 +197,11 @@ public class SearchApi : BaseApi
public async Task<SearchPage<Studio>> SearchStudios(
[FromQuery] string? q,
[FromQuery] Sort<Studio> sortBy,
[FromQuery] Filter<Studio>? filter,
[FromQuery] SearchPagination pagination,
[FromQuery] Include<Studio> fields
)
{
return SearchPage(await _searchManager.SearchStudios(q, sortBy, pagination, fields));
return SearchPage(await _searchManager.SearchStudios(q, sortBy, filter, pagination, fields));
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using Kyoo.Abstractions.Models.Utils;
namespace Kyoo.Meiliseach;
public static class FilterExtensionMethods
{
public static string? CreateMeilisearchFilter<T>(this Filter<T>? filter)
{
return filter switch
{
Filter<T>.And and => $"({and.First.CreateMeilisearchFilter()}) AND ({and.Second.CreateMeilisearchFilter()})",
Filter<T>.Or or => $"({or.First.CreateMeilisearchFilter()}) OR ({or.Second.CreateMeilisearchFilter()})",
Filter<T>.Gt gt => $"{gt.Property} > {gt.Value}",
Filter<T>.Lt lt => $"{lt.Property} < {lt.Value}",
Filter<T>.Ge ge => $"{ge.Property} >= {ge.Value}",
Filter<T>.Le le => $"{le.Property} <= {le.Value}",
Filter<T>.Eq eq => $"{eq.Property} = {eq.Value}",
Filter<T>.Has has => $"{has.Property} = {has.Value}",
Filter<T>.Ne ne => $"{ne.Property} != {ne.Value}",
Filter<T>.Not not => $"NOT ({not.Filter.CreateMeilisearchFilter()})",
Filter<T>.CmpRandom => throw new ValidationException("Random comparison is not supported."),
_ => null
};
}
}

View File

@ -99,11 +99,12 @@ public class SearchManager : ISearchManager
public Task<SearchPage<ILibraryItem>.SearchResult> SearchItems(
string? query,
Sort<ILibraryItem> sortBy,
Filter<ILibraryItem>? filter,
SearchPagination pagination,
Include<ILibraryItem>? include = default
)
{
return _Search("items", query, null, sortBy, pagination, include);
return _Search("items", query, filter.CreateMeilisearchFilter(), sortBy, pagination, include);
}
/// <inheritdoc/>
@ -143,22 +144,24 @@ public class SearchManager : ISearchManager
public Task<SearchPage<Episode>.SearchResult> SearchEpisodes(
string? query,
Sort<Episode> sortBy,
Filter<Episode>? filter,
SearchPagination pagination,
Include<Episode>? include = default
)
{
return _Search(nameof(Episode), query, null, sortBy, pagination, include);
return _Search(nameof(Episode), query, filter.CreateMeilisearchFilter(), sortBy, pagination, include);
}
/// <inheritdoc/>
public Task<SearchPage<Studio>.SearchResult> SearchStudios(
string? query,
Sort<Studio> sortBy,
Filter<Studio>? filter,
SearchPagination pagination,
Include<Studio>? include = default
)
{
return _Search(nameof(Studio), query, null, sortBy, pagination, include);
return _Search(nameof(Studio), query, filter.CreateMeilisearchFilter(), sortBy, pagination, include);
}
private class IdResource