Skip to content

Commit

Permalink
Support facet on IEnumerable property
Browse files Browse the repository at this point in the history
- Add methods for supporting facet for IEnumerable property
- Add unit tests for feature
  • Loading branch information
ManhOptimizely committed Oct 17, 2024
1 parent a1f1f13 commit c5780a1
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 11 deletions.
39 changes: 29 additions & 10 deletions APIs/src/EpiServer.ContentGraph/Api/Querying/TypeQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using EPiServer.ServiceLocation;
using EPiServer.ContentGraph.ExpressionHelper;
using System.Text.RegularExpressions;
using EPiServer.ContentGraph.Api.Result;

namespace EPiServer.ContentGraph.Api.Querying
{
Expand Down Expand Up @@ -271,6 +272,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 @@ -303,9 +310,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 @@ -599,14 +622,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 @@ -680,9 +701,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
23 changes: 22 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
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{Nesteds{NestedProperty{name count}}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.Nesteds, 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{Nesteds{NestedProperty(limit: 10){name count}}}";
const string expectedFullQuery = $"RequestTypeObject{{{expectedFields} {expectedFacet}}}";

typeQueryBuilder.Field(x => x.Property1);
typeQueryBuilder.Facet(x => x.Nesteds, 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; }
}
}

0 comments on commit c5780a1

Please sign in to comment.