Delivery API: Adding support for "Contains" filters (#14289)
* Adding support for contains filters * Making a dedicated name filter and making changes to the sort indexer * Fixed the merge from release/12.0 * Make the "name" filter support OR for comma separated filter values --------- Co-authored-by: kjac <kja@umbraco.dk>
This commit is contained in:
committed by
GitHub
parent
53e0227c98
commit
fcf477191f
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Api.Delivery.Indexing.Filters;
|
||||
|
||||
public sealed class NameFilterIndexer : IContentIndexHandler
|
||||
{
|
||||
internal const string FieldName = "name";
|
||||
|
||||
public IEnumerable<IndexFieldValue> GetFieldValues(IContent content, string? culture)
|
||||
=> new[] { new IndexFieldValue { FieldName = FieldName, Values = new object[] { content.GetCultureName(culture) ?? string.Empty } } };
|
||||
|
||||
public IEnumerable<IndexField> GetFields()
|
||||
=> new[] { new IndexField { FieldName = FieldName, FieldType = FieldType.StringAnalyzed, VariesByCulture = true } };
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Cms.Api.Delivery.Indexing.Sorts;
|
||||
|
||||
public sealed class NameSortIndexer : IContentIndexHandler
|
||||
{
|
||||
internal const string FieldName = "name";
|
||||
internal const string FieldName = "sortName";
|
||||
|
||||
public IEnumerable<IndexFieldValue> GetFieldValues(IContent content, string? culture)
|
||||
=> new[] { new IndexFieldValue { FieldName = FieldName, Values = new object[] { content.GetCultureName(culture) ?? string.Empty } } };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Umbraco.Cms.Api.Delivery.Indexing.Sorts;
|
||||
using Umbraco.Cms.Api.Delivery.Indexing.Filters;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Delivery.Querying.Filters;
|
||||
|
||||
@@ -16,16 +16,16 @@ public sealed class NameFilter : IFilterHandler
|
||||
public FilterOption BuildFilterOption(string filter)
|
||||
{
|
||||
var value = filter.Substring(NameSpecifier.Length);
|
||||
var negate = value.StartsWith('!');
|
||||
var values = value.TrimStart('!').Split(Constants.CharArrays.Comma);
|
||||
|
||||
return new FilterOption
|
||||
{
|
||||
FieldName = NameSortIndexer.FieldName,
|
||||
Values = value.IsNullOrWhiteSpace() == false
|
||||
? new[] { value.TrimStart('!') }
|
||||
: Array.Empty<string>(),
|
||||
Operator = value.StartsWith('!')
|
||||
? FilterOperation.IsNot
|
||||
: FilterOperation.Is
|
||||
FieldName = NameFilterIndexer.FieldName,
|
||||
Values = values,
|
||||
Operator = negate
|
||||
? FilterOperation.DoesNotContain
|
||||
: FilterOperation.Contains
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Examine;
|
||||
using Examine.Lucene.Providers;
|
||||
using Examine.Lucene.Search;
|
||||
using Examine.Search;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core;
|
||||
@@ -77,7 +79,14 @@ internal sealed class ApiContentQueryProvider : IApiContentQueryProvider
|
||||
|
||||
private IBooleanOperation BuildSelectorOperation(SelectorOption selectorOption, IIndex index, string culture)
|
||||
{
|
||||
IQuery query = index.Searcher.CreateQuery();
|
||||
// Needed for enabling leading wildcards searches
|
||||
BaseLuceneSearcher searcher = index.Searcher as BaseLuceneSearcher ?? throw new InvalidOperationException($"Index searcher must be of type {nameof(BaseLuceneSearcher)}.");
|
||||
|
||||
IQuery query = searcher.CreateQuery(
|
||||
IndexTypes.Content,
|
||||
BooleanOperation.And,
|
||||
searcher.LuceneAnalyzer,
|
||||
new LuceneSearchOptions { AllowLeadingWildcard = true });
|
||||
|
||||
IBooleanOperation selectorOperation = selectorOption.Values.Length == 1
|
||||
? query.Field(selectorOption.FieldName, selectorOption.Values.First())
|
||||
@@ -103,6 +112,23 @@ internal sealed class ApiContentQueryProvider : IApiContentQueryProvider
|
||||
}
|
||||
}
|
||||
|
||||
void HandleContains(IQuery query, string fieldName, string[] values)
|
||||
{
|
||||
if (values.Length == 1)
|
||||
{
|
||||
// The trailing wildcard is added automatically
|
||||
query.Field(fieldName, (IExamineValue)new ExamineValue(Examineness.ComplexWildcard, $"*{values[0]}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The trailing wildcard is added automatically
|
||||
IExamineValue[] examineValues = values
|
||||
.Select(value => (IExamineValue)new ExamineValue(Examineness.ComplexWildcard, $"*{value}"))
|
||||
.ToArray();
|
||||
query.GroupedOr(new[] { fieldName }, examineValues);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (FilterOption filterOption in filterOptions)
|
||||
{
|
||||
var values = filterOption.Values.Any()
|
||||
@@ -112,18 +138,16 @@ internal sealed class ApiContentQueryProvider : IApiContentQueryProvider
|
||||
switch (filterOption.Operator)
|
||||
{
|
||||
case FilterOperation.Is:
|
||||
// TODO: test this for explicit word matching
|
||||
HandleExact(queryOperation.And(), filterOption.FieldName, values);
|
||||
break;
|
||||
case FilterOperation.IsNot:
|
||||
// TODO: test this for explicit word matching
|
||||
HandleExact(queryOperation.Not(), filterOption.FieldName, values);
|
||||
break;
|
||||
// TODO: Fix
|
||||
case FilterOperation.Contains:
|
||||
HandleContains(queryOperation.And(), filterOption.FieldName, values);
|
||||
break;
|
||||
// TODO: Fix
|
||||
case FilterOperation.DoesNotContain:
|
||||
HandleContains(queryOperation.Not(), filterOption.FieldName, values);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
||||
@@ -68,7 +68,7 @@ internal sealed class DeliveryApiContentIndexFieldDefinitionBuilder : IDeliveryA
|
||||
FieldType.Number => FieldDefinitionTypes.Integer,
|
||||
FieldType.StringRaw => FieldDefinitionTypes.Raw,
|
||||
FieldType.StringAnalyzed => FieldDefinitionTypes.FullText,
|
||||
FieldType.StringSortable => FieldDefinitionTypes.FullTextSortable,
|
||||
FieldType.StringSortable => FieldDefinitionTypes.InvariantCultureIgnoreCase,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(field.FieldType))
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user