Skip to content

Commit 706f59b

Browse files
committed
Simplify and fix scoring issues - scoring does not matter when an expression is not true
1 parent db3b440 commit 706f59b

File tree

3 files changed

+12
-97
lines changed

3 files changed

+12
-97
lines changed

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/EvalOperator.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,9 @@ public void close() {
6363
public interface ExpressionEvaluator extends Releasable {
6464

6565
/**
66-
* Scoring value when an expression does not match (return false)
66+
* Scoring value when an expression does not match (return false) or does not contribute to the score
6767
*/
68-
double NO_MATCH_SCORE = -1.0;
69-
70-
/**
71-
* Default score for expressions that match (return true) but are not full text functions
72-
*/
73-
double MATCH_SCORE = 0.0;
68+
double NO_MATCH_SCORE = 0.0;
7469

7570
/** A Factory for creating ExpressionEvaluators. */
7671
interface Factory {
@@ -96,10 +91,10 @@ default boolean eagerEvalSafeInLazy() {
9691

9792
/**
9893
* Retrieves the score for the expression.
99-
* Only expressions that can be scored, or that can combine scores, should override this method
94+
* Only expressions that can be scored, or that can combine scores, should override this method.
10095
*/
10196
default DoubleBlock score(Page page, BlockFactory blockFactory) {
102-
return blockFactory.newConstantDoubleBlockWith(MATCH_SCORE, page.getPositionCount());
97+
return blockFactory.newConstantDoubleBlockWith(NO_MATCH_SCORE, page.getPositionCount());
10398
}
10499
}
105100

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/evaluator/EvalMapper.java

Lines changed: 6 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.elasticsearch.compute.data.BooleanBlock;
1515
import org.elasticsearch.compute.data.BooleanVector;
1616
import org.elasticsearch.compute.data.DoubleBlock;
17-
import org.elasticsearch.compute.data.DoubleVector;
1817
import org.elasticsearch.compute.data.ElementType;
1918
import org.elasticsearch.compute.data.Page;
2019
import org.elasticsearch.compute.data.Vector;
@@ -27,10 +26,8 @@
2726
import org.elasticsearch.xpack.esql.core.expression.Expression;
2827
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
2928
import org.elasticsearch.xpack.esql.core.expression.Literal;
30-
import org.elasticsearch.xpack.esql.core.tree.Source;
3129
import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper;
3230
import org.elasticsearch.xpack.esql.evaluator.mapper.ExpressionMapper;
33-
import org.elasticsearch.xpack.esql.evaluator.predicate.operator.logical.NotEvaluator;
3431
import org.elasticsearch.xpack.esql.expression.predicate.logical.BinaryLogic;
3532
import org.elasticsearch.xpack.esql.expression.predicate.logical.Not;
3633
import org.elasticsearch.xpack.esql.expression.predicate.nulls.IsNotNull;
@@ -215,43 +212,12 @@ public ExpressionEvaluator.Factory map(
215212
List<ShardContext> shardContexts,
216213
boolean usesScoring
217214
) {
218-
record NotScoreEvaluator(Source source, NotEvaluator notEval, ExpressionEvaluator innerEval, DriverContext driverContext)
219-
implements
220-
ExpressionEvaluator {
221-
@Override
222-
public Block eval(Page page) {
223-
return notEval.eval(page);
224-
}
225-
226-
@Override
227-
// NotEvaluator is a final, generated class - create this record to override score method
228-
public DoubleBlock score(Page page, BlockFactory blockFactory) {
229-
try (DoubleBlock scoreBlock = innerEval.score(page, blockFactory)) {
230-
DoubleVector scoreVector = scoreBlock.asVector();
231-
DoubleVector.Builder result = blockFactory.newDoubleVectorFixedBuilder(page.getPositionCount());
232-
// TODO We could optimize for constant vectors
233-
for (int i = 0; i < scoreVector.getPositionCount(); i++) {
234-
result.appendDouble(scoreVector.getDouble(i) == NO_MATCH_SCORE ? MATCH_SCORE : NO_MATCH_SCORE);
235-
}
236-
return result.build().asBlock();
237-
}
238-
}
239-
240-
@Override
241-
public void close() {
242-
Releasables.closeExpectNoException(notEval, innerEval);
243-
}
244-
}
245-
246-
return driverContext -> {
247-
var expEval = toEvaluator(foldCtx, not.field(), layout, shardContexts, usesScoring);
248-
ExpressionEvaluator innerEval = expEval.get(driverContext);
249-
NotEvaluator notEvaluator = new NotEvaluator(not.source(), innerEval, driverContext);
250-
if (usesScoring) {
251-
return new NotScoreEvaluator(not.source(), notEvaluator, innerEval, driverContext);
252-
}
253-
return notEvaluator;
254-
};
215+
var expEval = toEvaluator(foldCtx, not.field(), layout);
216+
return dvrCtx -> new org.elasticsearch.xpack.esql.evaluator.predicate.operator.logical.NotEvaluator(
217+
not.source(),
218+
expEval.get(dvrCtx),
219+
dvrCtx
220+
);
255221
}
256222
}
257223

@@ -400,22 +366,6 @@ public Block eval(Page page) {
400366
}
401367
}
402368

403-
@Override
404-
public DoubleBlock score(Page page, BlockFactory blockFactory) {
405-
// TODO We could skip re-evaluating the field if we store the result of eval()
406-
try (Block fieldBlock = field.eval(page)) {
407-
if (fieldBlock.asVector() != null) {
408-
return driverContext.blockFactory().newConstantDoubleBlockWith(NO_MATCH_SCORE, page.getPositionCount());
409-
}
410-
try (var builder = driverContext.blockFactory().newDoubleVectorFixedBuilder(page.getPositionCount())) {
411-
for (int p = 0; p < page.getPositionCount(); p++) {
412-
builder.appendDouble(p, fieldBlock.isNull(p) ? MATCH_SCORE : NO_MATCH_SCORE);
413-
}
414-
return builder.build().asBlock();
415-
}
416-
}
417-
}
418-
419369
@Override
420370
public void close() {
421371
Releasables.closeExpectNoException(field);
@@ -471,22 +421,6 @@ public Block eval(Page page) {
471421
}
472422
}
473423

474-
@Override
475-
public DoubleBlock score(Page page, BlockFactory blockFactory) {
476-
// TODO We could skip re-evaluating the field if we store the result of eval()
477-
try (Block fieldBlock = field.eval(page)) {
478-
if (fieldBlock.asVector() != null) {
479-
return driverContext.blockFactory().newConstantDoubleBlockWith(MATCH_SCORE, page.getPositionCount());
480-
}
481-
try (var builder = driverContext.blockFactory().newDoubleVectorFixedBuilder(page.getPositionCount())) {
482-
for (int p = 0; p < page.getPositionCount(); p++) {
483-
builder.appendDouble(p, fieldBlock.isNull(p) ? NO_MATCH_SCORE : MATCH_SCORE);
484-
}
485-
return builder.build().asBlock();
486-
}
487-
}
488-
}
489-
490424
@Override
491425
public void close() {
492426
Releasables.closeExpectNoException(field);

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/logical/BinaryLogicOperation.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
import java.util.function.BiFunction;
1313

14-
import static org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator.NO_MATCH_SCORE;
15-
1614
public enum BinaryLogicOperation implements PredicateBiFunction<Boolean, Boolean, Boolean> {
1715

1816
AND((l, r) -> {
@@ -23,11 +21,6 @@ public enum BinaryLogicOperation implements PredicateBiFunction<Boolean, Boolean
2321
return null;
2422
}
2523
return Boolean.logicalAnd(l.booleanValue(), r.booleanValue());
26-
}, (leftScore, rightScore) -> {
27-
if (NO_MATCH_SCORE == leftScore || NO_MATCH_SCORE == rightScore) {
28-
return NO_MATCH_SCORE;
29-
}
30-
return leftScore + rightScore;
3124
}, "AND"),
3225
OR((l, r) -> {
3326
if (Boolean.TRUE.equals(l) || Boolean.TRUE.equals(r)) {
@@ -37,20 +30,13 @@ public enum BinaryLogicOperation implements PredicateBiFunction<Boolean, Boolean
3730
return null;
3831
}
3932
return Boolean.logicalOr(l.booleanValue(), r.booleanValue());
40-
}, (leftScore, rightScore) -> {
41-
if (NO_MATCH_SCORE == leftScore || NO_MATCH_SCORE == rightScore) {
42-
return Math.max(leftScore, rightScore);
43-
}
44-
return leftScore + rightScore;
4533
}, "OR");
4634

4735
private final BiFunction<Boolean, Boolean, Boolean> process;
48-
private final BiFunction<Double, Double, Double> scoreFunction;
4936
private final String symbol;
5037

51-
BinaryLogicOperation(BiFunction<Boolean, Boolean, Boolean> process, BiFunction<Double, Double, Double> scoreFunction, String symbol) {
38+
BinaryLogicOperation(BiFunction<Boolean, Boolean, Boolean> process, String symbol) {
5239
this.process = process;
53-
this.scoreFunction = scoreFunction;
5440
this.symbol = symbol;
5541
}
5642

@@ -65,7 +51,7 @@ public Boolean apply(Boolean left, Boolean right) {
6551
}
6652

6753
public Double score(Double leftScore, Double rightScore) {
68-
return scoreFunction.apply(leftScore, rightScore);
54+
return leftScore + rightScore;
6955
}
7056

7157
@Override

0 commit comments

Comments
 (0)