Aggregates in the socket (ElasticSearch) for child / nested objects

I have a catalog of products for which I want to calculate units. It is simple enough for top-level properties such as brand name, manufacturer, etc. The problem is an attempt to calculate the calculation of price ranges, because we sell in different currencies, and when determining these indicators, I only want to request one currency at a time. Here is an example of my mapping of product objects:

public class Product { public int ID { get; set;} public string Name { get; set; } public IList<Price> Prices { get; set; } } public class Price { public int CurrencyID { get; set; } public decimal Cost { get; set; } } 

Here is an example request for all products with a price below 100:

 var cheapProducts = client.Search<Product>(s => s .From(0) .Size(1000) .Query(q => q .Range(r => r .LowerOrEquals(100) .OnField(f => f.Prices.FirstOrDefault().Cost)))); 

The ElasticSearch query that it generates is:

 { "from": 0, "size": 1000, "query": { "range" : { "prices.cost": { "lte": "100" } } } } 

This returns all products with at least one price below 100 in any currency, as you would expect. What I could not do was launch this request against the price in this currency. For example, adding this filter to a query deletes only those products that have no price in currency 1:

 var cheapProducts = client.Search<Product>(s => s .From(0) .Size(1000) .Filter(f => f .Term(t => t .Prices.FirstOrDefault().CurrencyID, 1)) .Query(q => q .Range(r => r .LowerOrEquals(100) .OnField(f => f.Prices.FirstOrDefault().Cost)))); 

I tried looking at the price list of both the nested object and the child, but ElasticSearch does not seem to index the prices this way because I get the error message "AggregationExecutionException [[nested] nested path [price] not nested]] and similar queries HasChild: Can queries and aggregates be generated this way?

+6
source share
1 answer

First you need to map the nested type:

  public class Product { public int ID { get; set; } public string Name { get; set; } [ElasticProperty(Type = FieldType.Nested)] public IList<Price> Prices { get; set; } } 

After that, try this query:

  var cheapProducts = client.Search<Product>(s => s .From(0) .Size(1000) .Query(x => x.Term(p => p .Prices.First().CurrencyID, 1) && x.Range(r => r .LowerOrEquals(100) .OnField(f => f.Prices.FirstOrDefault().Cost)))); 
+3
source

Source: https://habr.com/ru/post/979711/


All Articles