# How to make facet search by multiple nested fields in Elasticsearch Java API Client?

**URL:** <https://discuss.elastic.co/t/how-to-make-facet-search-by-multiple-nested-fields-in-elasticsearch-java-api-client/370655>\
**Category:** Elasticsearch\
**Tags:** language-clients\
**Created:** [November 17, 2024, 9:28am UTC](https://discuss.elastic.co/t/how-to-make-facet-search-by-multiple-nested-fields-in-elasticsearch-java-api-client/370655 "2024-11-17T09:28:35Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![AssHands](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/asshands/32/139287_2.png) [@AssHands](https://discuss.elastic.co/u/AssHands)\
**Post date:** [November 17, 2024, 9:28am UTC](https://discuss.elastic.co/t/how-to-make-facet-search-by-multiple-nested-fields-in-elasticsearch-java-api-client/370655/1 "2024-11-17T09:28:35Z")

</div>

There are my example documents

```auto
"id" : "1",
"title" : "test",
"description" : "test",
"price" : 100.0,
"category_id" : "1",
"characteristics" : [
  {
    "characteristic_id" : "1",
    "text_value" : "red"
  },
  {
    "characteristic_id" : "2",
    "numeric_value" : 15
  },
  {
    "characteristic_id" : "3",
    "numeric_value" : 20
  }
]

"id" : "2",
"title" : "test",
"description" : "test",
"price" : 200.0,
"category_id" : "1",
"characteristics" : [
  {
    "characteristic_id" : "1",
    "text_value" : "blue"
  },
  {
    "characteristic_id" : "2",
    "numeric_value" : 10
  },
  {
    "characteristic_id" : "3",
    "numeric_value" : 5
  }
]

```

And a query to my index must be like this. How can i write this using new Java Api Client for Elasticsearch?

```auto
GET product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "characteristics",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "characteristics.characteristic_id": 1
                    }
                  },
                  {
                    "term": {
                      "characteristics.text_value": "blue"
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "characteristics",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "characteristics.characteristic_id": 3
                    }
                  },
                  {
                    "range": {
                      "characteristics.numeric_value": {
                        "gte": 1,
                        "lte": 7
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "term": {
            "category_id": 1
          }
        },
        {
          "range": {
            "price": {
              "gt": 10.0,
              "lt": 500.0
            }
          }
        }
      ],
      "should": [
        {          
          "match": {
            "title": "te"
          }
        }
      ]
    }
  }
}

```

There is very little information in the official documentation. Should I even use this API if there is no normal documentation for it and write all the requests manually?

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [November 17, 2024, 9:58am UTC](https://discuss.elastic.co/t/how-to-make-facet-search-by-multiple-nested-fields-in-elasticsearch-java-api-client/370655/2 "2024-11-17T09:58:00Z")

</div>

I wrote some tips on how to use the IDE autocompletion to help writing Java code against the Java client.

> **[Switching from the Java High Level Rest Client to the new Java API Client](https://www.elastic.co/blog/switching-from-the-java-high-level-rest-client-to-the-new-java-api-client)**
>
> Let's say you have a Java project using Elastic 7.17 and the deprecated High Level Rest Client (HLRC). You have been asked to switch to Elastic 8.11 but the HLRC does not exist for this version. This ...

Hope this helps.

---

<div class="post-metadata">

**Author:** ![AssHands](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/asshands/32/139287_2.png) [@AssHands](https://discuss.elastic.co/u/AssHands)\
**Post date:** [November 17, 2024, 10:51am UTC](https://discuss.elastic.co/t/how-to-make-facet-search-by-multiple-nested-fields-in-elasticsearch-java-api-client/370655/3 "2024-11-17T10:51:09Z")

</div>

i did it.

```auto
        List<Query> filters = new ArrayList<>();

        if(requestPayload.getPriceTo() != 0) {
            filters.add(RangeQuery.of(r -> r
                            .field("price")
                            .gte(JsonData.of(requestPayload.getPriceFrom()))
                            .lte(JsonData.of(requestPayload.getPriceTo())))
                    ._toQuery());
        }

        if(requestPayload.getCategoryId() != null) {
            filters.add(TermQuery.of(t -> t
                    .field("category_id")
                    .value(requestPayload.getCategoryId()))
                    ._toQuery());
        }

        List<RangeQuery> rangeList = new ArrayList<>();
        for(var category : requestPayload.getFilters().getNumericValues()) {
            for (var numericValue : category.getValues()) {
                if (numericValue.getFrom() != null && numericValue.getTo() != null) {
                    rangeList.add(RangeQuery.of(r -> r
                            .field("characteristics.numeric_value")
                            .gte(JsonData.of(numericValue.getFrom()))
                            .lte(JsonData.of(numericValue.getTo()))));
                }
            }

            filters.add(NestedQuery.of(n -> n
                    .path("characteristics")
                    .query(q -> q
                            .bool(b -> {
                                b.must(m -> m
                                        .term(t -> t
                                                .field("characteristics.characteristic_id")
                                                .value(category.getCharacteristicId())));

                                for (RangeQuery rangeQuery : rangeList)
                                    b.should(s -> s.range(rangeQuery));

                                b.minimumShouldMatch("1");
                                return b;
                            })
                    ))._toQuery());
        }

        for(var category : requestPayload.getFilters().getTextValues()) {

            List<FieldValue> textValuesList = new ArrayList<>();
            for(var textValue : category.getValues()) {
                textValuesList.add(FieldValue.of(textValue));
            }

            TermsQueryField textValues = TermsQueryField.of(tf -> tf.value(textValuesList));
            if(!textValuesList.isEmpty()) {
                filters.add(NestedQuery.of(n -> n
                                .path("characteristics")
                                .query(q -> q
                                        .bool(b -> b
                                                .must(m -> m
                                                        .term(t -> t
                                                                .field("characteristics.characteristic_id")
                                                                .value(category.getCharacteristicId())))
                                                .must(m -> m
                                                        .terms(t -> t
                                                                .field("characteristics.text_value")
                                                                .terms(textValues))))))
                        ._toQuery());
            }
        }

        BoolQuery boolQuery = BoolQuery.of(b -> b
                .filter(filters)
                .should(s -> s
                        .match(m -> m
                                .field("title")
                                .query(requestPayload.getText()))));

        SearchResponse<ProductDocument> response = esClient.search(s -> s
                        .index("product")
                        .query(q -> q.bool(boolQuery)),
                ProductDocument.class);

        List<Hit<ProductDocument>> hits = response.hits().hits();
        for (Hit<ProductDocument> hit: hits) {
            System.out.println(hit.source());
        }

```
