Raouf Zouaoui
Raouf Zouaoui

Reputation: 1

How to combine must and should for the same field in filter Elasticsearch Spring Boot?

I'm using Elasticsearch filters and I would like to apply a must condition for selected regions (e.g., Occitanie and Île-de-France). Additionally, I want to ensure that profiles with the region "Toute la France" are also included in the search results, even if they are not part of the selected regions.

Currently, I am doing the following:

if (regions != null && !regions.isEmpty()) { 

BoolQuery.Builder finalQuery = new BoolQuery.Builder();
      
  for (String regionName : regions) {
            finalQuery.must(Query.of(q -> q.nested(n -> n
                    .path("regions")
                    .query(Query.of(inner -> inner.match(m -> m
                            .field("regions.regionName")
                            .query(regionName)
                    )))
            )));
        }

        finalQuery.should(Query.of(q -> q.nested(n -> n
                .path("regions")
                .query(Query.of(inner -> inner.match(m -> m
                        .field("regions.regionName")
                        .query("Toute la France")
                        .boost(4.0f)
                )))
        )));

        finalQuery.minimumShouldMatch("1");

        boolQuery.filter(Query.of(q -> q.bool(finalQuery.build())));
    }

However, this query only returns profiles that match the selected regions (must), but it does not include profiles with "Toute la France."

How can I modify the query to include profiles with "Toute la France" along with the selected regions?

Thanks in advance for your help!

Upvotes: 0

Views: 29

Answers (1)

Charchit Kapoor
Charchit Kapoor

Reputation: 9284

You need to generate a query using two bool queries:

if (regions != null && !regions.isEmpty()) { 

  BoolQuery.Builder regionsQuery = new BoolQuery.Builder();    
  for (String regionName : regions) {
       regionsQuery.must(Query.of(q -> q.nested(n -> n
                   .path("regions")
                   .query(Query.of(inner -> inner.match(m -> m
                          .field("regions.regionName")
                          .query(regionName)
                    )))
            )));
   }
   BoolQuery.Builder touteLaFranceQuery = new BoolQuery.Builder();           
   touteLaFranceQuery.must(Query.of(q -> q.nested(n -> n
             .path("regions")
             .query(Query.of(inner -> inner.match(m -> m
                    .field("regions.regionName")
                    .query("Toute la France")
              )))
   )));
   BoolQuery.Builder finalQuery = new BoolQuery.Builder();
   finalQuery.should(Query.of(q -> q.bool(regionsQuery.build()))
             .should(Query.of(q -> q.bool(touteLaFranceQuery.build()));    
   finalQuery.minimumShouldMatch(1);
}

Please note that there might be some syntactical issues. I hope you get the idea.

Upvotes: 0

Related Questions