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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.