Skip to content
This repository was archived by the owner on Aug 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions APIs/src/EpiServer.ContentGraph/Api/Querying/TypeQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ public TypeQueryBuilder<T> Autocomplete(Expression<Func<T, object>> fieldSelecto
}
return this;
}
private void SetFacetClause(string facetClause)
{
graphObject.Facets = graphObject.Facets.IsNullOrEmpty() ?
$"{facetClause}" :
$"{graphObject.Facets} {facetClause}";
}
/// <summary>
/// Get facet by field
/// </summary>
Expand Down Expand Up @@ -324,9 +330,25 @@ public TypeQueryBuilder<T> Facet(Expression<Func<T, int>> fieldSelector)
public TypeQueryBuilder<T> Facet(string propertyName)
{
string facet = ConvertNestedFieldToString.ConvertNestedFieldForFacet(propertyName);
graphObject.Facets = graphObject.Facets.IsNullOrEmpty() ?
$"{facet}" :
$"{graphObject.Facets} {facet}";
SetFacetClause(facet);
return this;
}
public TypeQueryBuilder<T> Facet<TField>(Expression<Func<T, IEnumerable<TField>>> enumSelector, Expression<Func<TField, object>> fieldSelector)
{
enumSelector.ValidateNotNullArgument("enumSelector");
fieldSelector.ValidateNotNullArgument("fieldSelector");
var combinePath = $"{enumSelector.GetFieldPath()}.{fieldSelector.GetFieldPath()}";
Facet(combinePath);
return this;
}
public TypeQueryBuilder<T> Facet<TField>(Expression<Func<T, IEnumerable<TField>>> enumSelector, Expression<Func<TField, FacetFilter>> fieldSelector)
{
enumSelector.ValidateNotNullArgument("enumSelector");
fieldSelector.ValidateNotNullArgument("fieldSelector");
var parse = new FacetExpressionParser();
var facetFilter = parse.GetFacetFilter(fieldSelector);

SetFacetClause($"{enumSelector.GetFieldPath()}{{{facetFilter.FilterClause}}}");
return this;
}
public TypeQueryBuilder<T> Total(bool? isAll = null)
Expand Down Expand Up @@ -708,14 +730,12 @@ public TypeQueryBuilder<T> Where<TField>(string fieldPath, IFilterOperator filte
Where(fieldPath, filterOperator);
return this;
}
private TypeQueryBuilder<T> Facet(string propertyName, IFacetOperator facetFilter)
public TypeQueryBuilder<T> Facet(string propertyName, IFacetOperator facetFilter)
{
propertyName.ValidateNotNullArgument("propertyName");
facetFilter.ValidateNotNullArgument("facetFilter");
string facets = ConvertNestedFieldToString.ConvertNestedFieldForFacet(propertyName, facetFilter);
graphObject.Facets = graphObject.Facets.IsNullOrEmpty() ?
$"{facets}" :
$"{graphObject.Facets} {facets}";
SetFacetClause(facets);
return this;
}
public TypeQueryBuilder<T> Facet(Expression<Func<T, object>> fieldSelector, IFacetOperator facetFilter)
Expand Down Expand Up @@ -789,9 +809,7 @@ public TypeQueryBuilder<T> Facet(Expression<Func<T, DateTime?>> fieldSelector, D
public TypeQueryBuilder<T> Facet(IFacetFilter facetFilter)
{
facetFilter.ValidateNotNullArgument("facetFilter");
graphObject.Facets = graphObject.Facets.IsNullOrEmpty() ?
$"{facetFilter.FilterClause}" :
$"{graphObject.Facets} {facetFilter.FilterClause}";
SetFacetClause(facetFilter.FilterClause);
return this;
}
public TypeQueryBuilder<T> FilterForVisitor(params IFilterForVisitor[] filterForVisitors)
Expand Down
55 changes: 54 additions & 1 deletion APIs/src/EpiServer.ContentGraph/Extensions/FacetExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,31 @@ namespace EPiServer.ContentGraph.Extensions
{
public static class FacetExtension
{
public static DelegateFacetFilterBuilder FacetLimit(this object field, int limit=5)
public static DelegateFacetFilterBuilder FacetLimit(this object field, int limit = 5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}
public static DelegateFacetFilterBuilder FacetLimit(this string field, int limit=5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}
public static DelegateFacetFilterBuilder FacetLimit(this float field, int limit = 5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}
public static DelegateFacetFilterBuilder FacetLimit(this double field, int limit = 5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}
public static DelegateFacetFilterBuilder FacetLimit(this int field, int limit = 5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}
public static DelegateFacetFilterBuilder FacetLimit(this bool field, int limit = 5)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Limit(limit)));
}

public static DelegateFacetFilterBuilder FacetFilters(this string field, params string[] values)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new StringFacetFilterOperators().Filters(values)));
Expand Down Expand Up @@ -66,5 +87,37 @@ public static DelegateFacetFilterBuilder FacetInRange(this IEnumerable<float> fi
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges((from, to))));
}
public static DelegateFacetFilterBuilder FacetInRanges(this float field, params (float? from, float? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this IEnumerable<float> field, params (float? from, float? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this double field, params (double? from, double? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this IEnumerable<double> field, params (double? from, double? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this int field, params (int? from, int? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this IEnumerable<int> field, params (int? from, int? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this long field, params (long? from, long? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
public static DelegateFacetFilterBuilder FacetInRanges(this IEnumerable<long> field, params (long? from, long? to)[] ranges)
{
return new DelegateFacetFilterBuilder(field => new TermFacetFilter(field, new NumericFacetFilterOperators().Ranges(ranges)));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using EPiServer.ContentGraph.Api.Querying;
using EpiServer.ContentGraph.UnitTests.QueryTypeObjects;
using Xunit;
using EPiServer.ContentGraph.Extensions;

namespace EpiServer.ContentGraph.UnitTests.ExtensionTests
{
[CollectionDefinition("Facet extension tests")]
public class FacetExtensionTests
{
TypeQueryBuilder<RequestTypeObject> typeQueryBuilder;
public FacetExtensionTests()
{
typeQueryBuilder = new TypeQueryBuilder<RequestTypeObject>();
}

[Fact]
public void generate_facet_filter_with_extension()
{
const string expectedFields = "items{Property1}";
const string expectedFacet = "facets{Property1(filters: [\"test\"]){name count}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.Property1.FacetFilters("test"));

var query = typeQueryBuilder.ToQuery().GetQuery();

Assert.NotNull(query);
Assert.Contains(expectedFacet, query.Query);
Assert.Equal(query.Query, expectedFullQuery);
}
[Fact]
public void generate_facet_limit_with_extension()
{
const string expectedFields = "items{Property1}";
const string expectedFacet = "facets{Property1(limit: 10){name count}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.Property1.FacetLimit(10));

var query = typeQueryBuilder.ToQuery().GetQuery();

Assert.NotNull(query);
Assert.Contains(expectedFacet, query.Query);
Assert.Equal(query.Query, expectedFullQuery);
}
[Fact]
public void generate_facet_with_IEnumerable()
{
const string expectedFields = "items{Property1}";
const string expectedFacet = "facets{NestedObjects{NestedProperty{name count}}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.NestedObjects, f=> f.NestedProperty);

var query = typeQueryBuilder.ToQuery().GetQuery();

Assert.NotNull(query);
Assert.Contains(expectedFacet, query.Query);
Assert.Equal(query.Query, expectedFullQuery);
}
[Fact]
public void generate_facet_limit_with_IEnumerable()
{
const string expectedFields = "items{Property1}";
const string expectedFacet = "facets{NestedObjects{NestedProperty(limit: 10){name count}}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.NestedObjects, f => f.NestedProperty.FacetLimit(10));

var query = typeQueryBuilder.ToQuery().GetQuery();

Assert.NotNull(query);
Assert.Contains(expectedFacet, query.Query);
Assert.Equal(query.Query, expectedFullQuery);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
internal class NestedObject
{
public int NestedProperty { get; set; }
public string NestedStringProperty { get; set; }
}
}
Loading