Home > Software engineering >  Elastic Search / Hibernate Search : how to code xor operator with query DSL API in java?
Elastic Search / Hibernate Search : how to code xor operator with query DSL API in java?

Time:09-27

I'am using hibernate search java API to generate an elastic search query. I have problem to code a xor operator. Typically I wrote :

private void applyXorOperator(BooleanPredicateClausesStep<?> boolClausesAppender,
                                  BooleanPredicateClausesStep<?> firstBool,
                                  BooleanPredicateClausesStep<?> secondBool) {

        boolClausesAppender.should(
        boolClausesAppender.must(firstBool).mustNot(secondBool));
        boolClausesAppender.should(
                boolClausesAppender.mustNot(firstBool).must(secondBool));
        boolClausesAppender.minimumShouldMatchNumber(1);
    }

How do I say "not both", I was expecting :

boolClausesAppender.maximumShouldMatchNumber(1);

but this method doesn't exist in the API. Any solution ?

Thx.

CodePudding user response:

By definition:

a XOR b <=> (a AND NOT b) OR (NOT a AND b)

So just implement it that way:

private void applyXorOperator(BooleanPredicateClausesStep<?> boolClausesAppender,
                                  BooleanPredicateClausesStep<?> firstBool,
                                  BooleanPredicateClausesStep<?> secondBool) {
    SearchPredicate a = firstBool.toPredicate();
    SearchPredicate b = secondBool.toPredicate();

    boolClausesAppender.should(f -> f.bool()
         // a AND NOT b
         .should(f.bool().must(a).mustNot(b))
         // OR (NOT a AND b)
         .should(f.bool().mustNot(a).must(b)));
}

EDIT: By the way, you don't need first/second to be boolean predicates. This would work too, and seems simpler:

private void applyXorOperator(BooleanPredicateClausesStep<?> boolClausesAppender,
                                  PredicateFinalStep first,
                                  PredicateFinalStep second) {
    SearchPredicate a = first.toPredicate();
    SearchPredicate b = second.toPredicate();

    boolClausesAppender.should(f -> f.bool()
         // a AND NOT b
         .should(f.bool().must(a).mustNot(b))
         // OR (NOT a AND b)
         .should(f.bool().mustNot(a).must(b)));
}
  • Related