mancini0
mancini0

Reputation: 4713

Spring-Data-Elasticsearch chaining "OR" criteria with "AND" criteria

Chaining OR criteria to an AND criteria is not working as expected. Say I want to find all green colored clothing articles made of cotton that are either duty free OR originate in India. I would expect the below code to accomplish that:

List<Criteria> andConditions = new ArrayList<>();
List<Criteria> orConditions = new ArrayList<>();

    andConditions.add(new Criteria("color").is("green"));
    andConditions.add(new Criteria("fabric").is("cotton"));

    orConditions.add(new Criteria("countryOfOrigin").is("INDIA"));
    orConditions.add(new Criteria("isDutyFree").is(true));


    Criteria andCriteria=new Criteria();
    Criteria orCriteria=null; //to avoid new Criteria().or(firstCriteriaInLoopBelow), since new Criteria() might match  everything...

    for(Criteria condition:andConditions){
       andCriteria=andCriteria.and(condition);
    }
    for(Criteria condition:orConditions){
       if(orCriteria==null){
           orCriteria=condition;
       }else{
           orCriteria=orCriteria.or(condition);
       }
    }


andCriteria=andCritiera.and(orCriteria);
CriteriaQuery query = new CriteriaQuery(andCriteria).setPageable(page);
elasticsearchTemplate.queryForPage(query, ClothingArticle.class)

Instead, the query seems to be ignoring the andCriteria entirely, and simply honors the OR criteria. In other words, I'm getting back all articles of clothing that are EITHER made in India OR duty free, independent of the color or fabric.

I found this Jira ticket on Spring's dashboard: DATAES-30 titled , ' "Or" criteria in CriteriaQuery is not getting generated correctly'

But the ticket seems rather old, and broken 'OR' functionality seems like a critical lack of functionality.

Does anybody have any suggestions for chaining an OR to and AND?

Thanks!

Upvotes: 3

Views: 2554

Answers (1)

mancini0
mancini0

Reputation: 4713

I was able to achieve the desired behavior using a SearchQuery. It seems the default minimumShouldMatch is 0, as before I set minimumShouldMatch to 1 the SearchQuery had the same behavior I encountered when using the Criteria.

BoolQueryBuilder filter= QueryBuilders.boolQuery()
          .must(QueryBuilders.termQuery("color", "green"))
          .must(QueryBuilders.termQuery("fabric","cotton"))
          .should(QueryBuilders.termQuery("countryOfOrigin","India"))
          .should(QueryBuilders.termQuery("isDutyFree",true))
          .minimumShouldMatch(1);

SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(matchAllQuery())
                .withFilter(filter)
                .withPageable(pageable)
                .build();

Page<ClothingArticle> clothes = elasticsearchTemplate.queryForPage(searchQuery, ClothingArticle.class);

Upvotes: 1

Related Questions