Nested queries
Nested queries in Episerver Find let you query a parent object and filter it on a child collection marked as "nested." This is particularly useful in solutions with Episerver Commerce and Find, to manage search queries in large catalog structures.
Nested field and types
Note: Episerver allows queries on complex types. If you want to query a value type or a string collection, use the Match or Exist filter.
Using function calls as nested fields
You can use functional calls, such as team.ForeignPlayers(), as a nested collection. The function must return an IEnumerable<TListItem> where TListItem:class.
Example: Include the function to be indexed (functions are not indexed by default).
client.Conventions.ForInstancesOf<Team>().IncludeField(team => team.ForeignPlayer());
Adding fields as nested types
To add desired fields as "nested" types, use one of these conventions, depending on your requirements.
Example: Nested property or function exists on a class, for example Team.
client.Conventions.NestedConventions.ForType<Team>().Add(team => team.Players);
Example: Nested property exists on an interface, for example, IPlayers (all implementations of this interface are marked as nested).
client.Conventions.NestedConventions.ForType<IPlayers>().Add(team => team.Players);
Example: Custom convention, which allows for a custom implemention. Type and name can be used to determine whether a specific property should be marked as nested.
client.Conventions.NestedConventions.Add((type, name) => (typeof(IPlayers).IsAssignableFrom(type) && name.Equals("Players")));
The above syntax allows Find's indexing, searching, and filtering to treat that field as one whose children can be used in filtering. For example:
public class Team
{
public Team(string name)
{
TeamName = name;
Players = new List<Player>();
}
public string TeamName { get; set; }
public List<Player> Players { get; set; }
}
public class Player
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}
Index the content and start filtering:
result = client.Search<Team>()
.Filter(x => x.Players, p => p.FirstName.Match("Cristiano") &
p.LastName.Match("Ronaldo"))
.GetResult();
or
result = client.Search<Team>()
.Filter(x => x.Players.MatchItem(p => p.FirstName.Match("Cristiano") &
p.LastName.Match("Ronaldo")))
.GetResult();
Sorting
To sort by nested properties, use the OrderBy extension, which takes a filter argument that specifies the nested object used to calculate the sort value.
result = client.Search<Team>()
.Filter(x => x.Players, p => p.FirstName.Match("Cristiano"))
.OrderBy(x => x.Players, p => p.LastName, p => p.FirstName.Match("Cristiano"))
.GetResult();
or
result = client.Search<Team>()
.Filter(x => x.Players, p => p.FirstName.Match("Cristiano"))
.OrderByDescending(x => x.Players, p => p.LastName, p =>
p.FirstName.Match("Cristiano"))
.GetResult();
For int/DateTime, specify a SortMode (Min/Max/Avg/Sum) to determine how to treat multiple sort values. For example, to sort by maximum player salary on a team, use:
result = client.Search<Team>()
.OrderByDescending(x => x.Players, p => p.Salary, SortMode.Max)
.GetResult();
Facets
To create facets on nested properties, the TermsFacetFor/HistogramFacetFor/DateHistogramFacetFor extensions take an IEnumerable expression along with an item expression and optional filter.
result = client.Search<Team>()
.TermsFacetFor(x => x.Players, x => x.FirstName)
.GetResult();
or (to filter):
result = client.Search<Team>()
.TermsFacetFor(x => x.Players, x => x.FirstName, x => x.LastName.Match("Ronaldo"))
.GetResult();
and to fetch the result:
facet = result.TermsFacetFor(x => x.Players, x => x.FirstName);
Last updated: Nov 16, 2015