1

I am using the new version 8.13 of Elasticsearch for a new search app and trying to imitate the below kind of logic using the new Java API client instead of using Java High Level Rest client which was deprecated now. I have to perform search from multiple indices including below queries-

1.multiple matchPhrasePrefixQuery like below

BoolQueryBuilder searchTheseFields = QueryBuilders.boolQuery();
for (String searchFields : searchTheseFieldsArray) {
        searchTheseFields .should(QueryBuilders.matchPhrasePrefixQuery(searchFields, **SearchText**));
            }

2.multiple term queries with fileds and values

BoolQueryBuilder filterFields = QueryBuilders.boolQuery();
for (Map.Entry<String, Object> entry : filterTheseFields.entrySet()) {
                filterFields.must(QueryBuilders.termQuery(entry.getKey(), entry.getValue()));
            }

3.multiple range queries

BoolQueryBuilder rangeFilter1 = QueryBuilders.boolQuery();
BoolQueryBuilder rangeFilter2 = QueryBuilders.boolQuery();

rangeFilter1.should(QueryBuilders.rangeQuery(key).gte("gteVal").lte("lteVal"))
                               .should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(key)));

And finally add all these queries to a single Query Builder like below and call using client.

BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(searchTheseFields)
                .must(filterFields)
                .filter(rangeFilter1);

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        searchSourceBuilder.from(data.getFrom());
        searchSourceBuilder.size(data.getSize());
        
SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(passing indices here);
        searchRequest.source(searchSourceBuilder);
        
SearchResponse response = client.search(searchRequest);

Issues I am facing while trying it using new Java Client - BoolQueryBuilder is not there which was used earlier to create different type of queries and aggregate all of them. As @Murat mentioned SearchSourceBuilder is also not there

So,can anyone help me to imitate the above code using new Java API Client of Elasticsearch new version 8 or above, like how We can create multiple different type queries and add all of them to a single query and call it using the client.

Thanks

5
  • What is the question? Commented May 3, 2024 at 12:18
  • @aled, I want the same logic using new Java API client without using Java High Level Rest Client. Commented May 3, 2024 at 13:02
  • Are those the existing queries or the new ones? Are you having an error? What is not working? Edit your question to make it clear. I recommend to read How to Ask. However if you are asking others to write code for you note that this is a Q&A site, not a programming for free coding service. Commented May 3, 2024 at 13:33
  • @aled, I am not asking to write the whole code I just need one example to imitate the same kind of logic when we have multiple fields? And I know how to write a question it is very clear if you are not getting what I am looking for you are free to leave it. Commented May 3, 2024 at 13:44
  • I'm just explaining how to use the site according to the guidelines. Commented May 3, 2024 at 13:48

2 Answers 2

0

Today I spent the whole time with this topic. Ok, initially you can read the relevant documentation. https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html

You can create separate queries like BoolQuery, RangeQuery, MultiMatchQuery, TermQuery etc. Tose are in the library under: https://artifacts.elastic.co/javadoc/co/elastic/clients/elasticsearch-java/8.13.2/co/elastic/clients/elasticsearch/_types/query_dsl/package-summary.html

Some examples:

String searchText = "bike";
double maxPrice = 200.0;

// Search by product name
Query byName = MatchQuery.of(m -> m 
    .field("name")
    .query(searchText)
)._toQuery(); 

// Search by max price
Query byMaxPrice = RangeQuery.of(r -> r
    .field("price")
    .gte(JsonData.of(maxPrice)) 
)._toQuery();

You may use the queries directly inside the client.search() which brings you the response from Elasticsearch.

Query aTermQuery = TermQuery.of(tq -> tq.field(myfield).term(myterm)._toQuery();

SearchResponse<MyClass> response = client.search(s -> s.query(q -> q.bool(b -> b
  .must(aTermQuery))), MyClass.class);

Or you can create a SearchRequest object, throw your queries inside it and use the same pattern with client.search().

Query byName = MatchQuery.of(m -> m 
    .field("name")
    .query(searchText)
)._toQuery(); 

SearchRequest mySearchRequest = new SearchRequest.Builder.query(byName).build().
SearchResponse<MyClass> response = client.search(mySearchRequest, MyClass.class);

There may be some small errors but I think it should deliver the simple logic. Good luck.

Edit: I could not find any SearchSourceBuilder in the new library. As I read, there is no such a class.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Murat, I got you I was also trying the same but got difficulties when I saw BoolQueryBuilder is not there like you mentioned SearchSourceBuilder is also not there. I will spend some more time and update here.
The first link doesn't exist anymore
0

Finally I have converted the above posted logic from Elasticsearch 7.16.2 Java High Level Rest Client to Elasticsearch 8.13.2 new Java Client.

1.multiple matchPhrasePrefixQuery

BoolQuery.Builder searchTheseFields = new BoolQuery.Builder();
for (String searchFields : searchTheseFieldsArray) {
            searchTheseFields.should(Query.of(q -> q
                    .matchPhrasePrefix(m -> m.field(searchFields).query("searchText"))));
        }

2.multiple term queries with fileds and values

BoolQuery.Builder filterFields = new BoolQuery.Builder();
for (Map.Entry<String, Object> entry : filterFieldsList.entrySet()) {
            filterFields.must(Query.of(
                    q -> q.term(t -> t.field(entry.getKey()).value(entry.getValue().toString().toLowerCase()))));
        }

3.multiple range queries

ArrayList<Query> rangeFilterQueries = new ArrayList<>();
Query rangeQuery1 = QueryBuilders.range().field(key).gte(JsonData.of(dateRange.get(0)))
                        .lte(JsonData.of(dateRange.get(1))).build()._toQuery();
                Query notExistsQuery1 = QueryBuilders.bool().mustNot(m -> m.exists(e -> e.field(key))).build()
                        ._toQuery();
                rangeFilterQueries
                    .add(QueryBuilders.bool().should(rangeQuery1).should(notExistsQuery1).build()._toQuery()); etc...

Building Final query

BoolQuery.Builder queryBuilder = new BoolQuery.Builder().must(searchTheseFields.build()._toQuery())
            .must(filterFields.build()._toQuery());

    for (Query rangeFilterQuery : rangeFilterQueries) {
        queryBuilder.filter(rangeFilterQuery);
    }

    Query finalQuery = queryBuilder.build()._toQuery();

Executing the query

SearchRequest searchRequest = new SearchRequest.Builder().index(indicesToSearchFrom).query(finalQuery)
            .from(offset).size(limit).build();

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.