This content is archived. See latest version here

Last updated: Nov 16 2015

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);

Do you have feedback on this documentation? Send an email to documentation@episerver.com. For development-related questions and discussions, refer to our Forums on https://world.episerver.com/forum/