2

I want to filter data in nested array using Nest. Given I have following classes:

public class Package
{
    public IEnumerable<PackageItem> PackageItems { get; set; }
}

public class PackageItem
{
    public string Title { get; set; }
    public decimal Price { get; set; }
}

and I have index these data in ElasticSearch using NEST: Here is my data:

"hits" : [
  {
    "_index" : "packages",
    "_type" : "_doc",
    "_id" : "cf08b05c-c8b5-45cb-bca8-17267c3613fb",
    "_score" : 1.0,
    "_source" : {
      "id" : "cf08b05c-c8b5-45cb-bca8-17267c3613fb",
      "PackageItems" : [
        {
          "Title" : "some-title",
          "price" : 100000.0
        },
        {
          "Title" : "some-title",
          "price" : 200000.0
        }
      ]
    }
  },
  {
    "_index" : "packages",
    "_type" : "_doc",
    "_id" : "39436cb3-483e-4fb4-92e4-4e06ecad27a1",
    "_score" : 1.0,
    "_source" : {
      "id" : "39436cb3-483e-4fb4-92e4-4e06ecad27a1",
      "PackageItems" : [
        {
          "Title" : "some-title",
          "price" : 100000.0
        },
        {
          "Title" : "some-title",
          "price" : 400000.0
        }
      ]
    }
  },
  {
    "_index" : "packages",
    "_type" : "_doc",
    "_id" : "cd5d3587-838b-46ec-babc-d756c5587396",
    "_score" : 1.0,
    "_source" : {
      "id" : "cd5d3587-838b-46ec-babc-d756c5587396",
      "PackageItems" : [
        {
          "Title" : "some-title",
          "price" : 300000.0
        },
        {
          "Title" : "some-title",
          "price" : 500000.0
        }
      ]
    }
  }
]

I want to filter packages with minimumPackageItemPrice:100000 and maximumPackageItemPrice:400000. What query should I execute using NEST?

The result should be like this:

"hits" : [
  {
    "_index" : "packages",
    "_type" : "_doc",
    "_id" : "cf08b05c-c8b5-45cb-bca8-17267c3613fb",
    "_score" : 1.0,
    "_source" : {
      "id" : "cf08b05c-c8b5-45cb-bca8-17267c3613fb",
      "PackageItems" : [
        {
          "Title" : "some-title",
          "price" : 100000.0
        },
        {
          "Title" : "some-title",
          "price" : 200000.0
        }
      ]
    }
  },
  {
    "_index" : "inventories",
    "_type" : "_doc",
    "_id" : "39436cb3-483e-4fb4-92e4-4e06ecad27a1",
    "_score" : 1.0,
    "_source" : {
      "id" : "39436cb3-483e-4fb4-92e4-4e06ecad27a1",
      "PackageItems" : [
        {
          "Title" : "some-title",
          "price" : 100000.0
        },
        {
          "Title" : "some-title",
          "price" : 400000.0
        }
      ]
    }
  }
]
2
  • Is PackageItems a nested field in your mapping? Commented Aug 8, 2020 at 20:25
  • Yes , it's nested Commented Aug 9, 2020 at 6:01

1 Answer 1

4

To trigger range queries on Elasticsearch through NEST, you can make use of the range query. The approach is that you can construct a range query for your scenario and trigger that query through the NEST client's search method.

Generating the range query for your case

// This method builds the range query where price should be between 
// 100000.0 and 400000.0 (inclusive range in this case)
private static QueryContainer BuildNestedRangeQuery()
{
    return new QueryContainerDescriptor<Package>()
        .Nested(n =>
            n.Path(p => p.PackageItems)
             .Query(q => q
                .Range(r => r
                    .Field(f => f.PackageItems.FirstOrDefault().Price)
                    .GreaterThanOrEquals(100000.0)
                    .LessThanOrEquals(400000.0))
                )
             )
        )
}

Triggering the search

Search can be triggered through the NEST client as shown below. This may vary according to your own implementation. However, the above range query remains the same.

// Replace T with type of your choice and client is NEST client
var result = client.Search<T>(    
    .From(0)
    .Size(20)
    .Query(q => BuildNestedRangeQuery())
    // other methods that you want to chain go here
)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.