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)));
}