3

I am trying to convert some Java High Level REST Client code to new Elasticsearch Java API Client.

I want to convert this query which retrieves the contents if the id is equal to 10 or 20.

SearchRequest searchRequest = new SearchRequest().indices(indexName);

    List<Long> ids = new ArrayList<>();
    ids.add(10l);
    ids.add(20l);

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

    searchSourceBuilder.query(QueryBuilders.boolQuery()
        .must(QueryBuilders.termQuery("id", ids)));

        searchRequest.source(searchSourceBuilder);

With the new Java API Client I've built something like this.

TermsQueryField termsQueryField = new TermsQueryField.Builder()
         .value(/*Expects List<FieldValue>*/)
         .build();

TermsQuery idTerms = new TermsQuery.Builder()
        .field("id")
        .terms(termsQueryField)
        .build();

Query idQuery = new Query.Builder()
        .terms(idTerms)
        .build();

BoolQuery boolQuery = new BoolQuery.Builder()
        .must(idQuery)
        .build();

Query query = new Query.Builder()
        .bool(boolQuery)
        .build();

SearchRequest searchRequest = new SearchRequest.Builder()
        .index(indexName)
        .query(query)
        .build();

I can add the termQuery options for single values but I could not find a way to add a list to the query.

I've came across with TermsQuery but that requires the values to be set as a List<FieldValue> so that's not very helpful.

Note: I know I can use lambda expressions for constructing these objects but I am trying to be as verbose as possible until I figure out how to use the new client.

5
  • 1
    You can create two different TermQuery query in a bool->should clause. You cannot send multiple values to TermQuery becasue it expects a single value. Or you can use the TermsQuery as you stated in your question Commented May 11, 2022 at 12:25
  • Have you tried building that List<FieldValue>? Should be straightforward enough: just instantiate an ArrayList and then do lst.add(FieldValue.of("strValue") Commented May 12, 2022 at 10:00
  • @ilvar Yes I know I can do that but that doesn't sound efficient. Why should I have to loop every ID just to create a query? There must be an easier way. That's what I am looking for. Commented May 13, 2022 at 7:38
  • 1
    Did you get anywhere with this? I'm trying to the same. I'm finding the new Java Client quite...cumbersome / terrible for examples Commented Nov 29, 2022 at 12:26
  • 1
    @MetaCoder I don't have any solutions at the moment. Sorry about that. I can't remember how I solved this but I believe it was not a pretty one so I did not post an answer. Commented Dec 1, 2022 at 12:43

3 Answers 3

6

Using streams seems currently to be the simplest way to create the list of terms:

List<String> countries = List.of("afg", "aus");

TermsQueryField countryTerms = new TermsQueryField.Builder()
    .value(countries.stream().map(FieldValue::of).toList())
    .build();

SearchRequest sr = SearchRequest.of(s -> s
    .query(q -> q
        .bool(b -> b 
            .filter(mCtry -> mCtry
                .bool(bCtry -> bCtry
                    .should(shdCtry -> shdCtry
                        .terms(tCtry -> tCtry
                            .field("country")
                            .terms(countryTerms)
                        )
                    )
                )
            )
        )
    )
);
Sign up to request clarification or add additional context in comments.

Comments

0

You can use boolQuery like this

boolQuery().apply {
            ids.forEach {
                should(matchQuery("test.id", it))
            }
        }

Above solution has a limit on the criterias to add. Otherwise use

(termsQuery("FIELD", [value1, value2,value3])

Comments

0

The below code is also working.

TermsQueryField countryTerms = new TermsQueryField.Builder()
.value(countries.stream().map(FieldValue::of).toList())
.build();

SearchRequest sr = SearchRequest.of(s -> s
            .query(q -> q
                    .bool(bCtry -> bCtry
                            .should(shdCtry -> shdCtry
                                    .terms(tCtry -> tCtry
                                            .field("country")
                                            .terms(countryTerms)
                                    )
                            )
                    )
            )
    );

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.