1414import org .elasticsearch .compute .data .BooleanBlock ;
1515import org .elasticsearch .compute .data .BooleanVector ;
1616import org .elasticsearch .compute .data .DoubleBlock ;
17+ import org .elasticsearch .compute .data .DoubleVector ;
1718import org .elasticsearch .compute .data .ElementType ;
1819import org .elasticsearch .compute .data .Page ;
1920import org .elasticsearch .compute .data .Vector ;
2627import org .elasticsearch .xpack .esql .core .expression .Expression ;
2728import org .elasticsearch .xpack .esql .core .expression .FoldContext ;
2829import org .elasticsearch .xpack .esql .core .expression .Literal ;
30+ import org .elasticsearch .xpack .esql .core .tree .Source ;
2931import org .elasticsearch .xpack .esql .evaluator .mapper .EvaluatorMapper ;
3032import org .elasticsearch .xpack .esql .evaluator .mapper .ExpressionMapper ;
33+ import org .elasticsearch .xpack .esql .evaluator .predicate .operator .logical .NotEvaluator ;
3134import org .elasticsearch .xpack .esql .expression .predicate .logical .BinaryLogic ;
3235import org .elasticsearch .xpack .esql .expression .predicate .logical .Not ;
3336import org .elasticsearch .xpack .esql .expression .predicate .nulls .IsNotNull ;
3841
3942import java .util .List ;
4043
44+ import static org .elasticsearch .compute .lucene .LuceneQueryExpressionEvaluator .NO_MATCH_SCORE ;
45+
4146public final class EvalMapper {
4247
4348 private static final List <ExpressionMapper <?>> MAPPERS = List .of (
@@ -185,7 +190,15 @@ public DoubleBlock score(Page page, BlockFactory blockFactory) {
185190 // TODO We could optimize for constant vectors
186191 try (var result = lhs .blockFactory ().newDoubleVectorFixedBuilder (positionCount )) {
187192 for (int p = 0 ; p < positionCount ; p ++) {
188- result .appendDouble (p , lhs .getDouble (p ) + rhs .getDouble (p ));
193+ double l = lhs .getDouble (p );
194+ double r = rhs .getDouble (p );
195+ if (l == NO_MATCH_SCORE ) {
196+ result .appendDouble (p , r );
197+ } else if (r == NO_MATCH_SCORE ) {
198+ result .appendDouble (p , l );
199+ } else {
200+ result .appendDouble (p , l + r );
201+ }
189202 }
190203 return result .build ().asBlock ();
191204 }
@@ -210,12 +223,43 @@ public ExpressionEvaluator.Factory map(
210223 List <ShardContext > shardContexts ,
211224 boolean usesScoring
212225 ) {
213- var expEval = toEvaluator (foldCtx , not .field (), layout , shardContexts , usesScoring );
214- return dvrCtx -> new org .elasticsearch .xpack .esql .evaluator .predicate .operator .logical .NotEvaluator (
215- not .source (),
216- expEval .get (dvrCtx ),
217- dvrCtx
218- );
226+ record NotScoreEvaluator (Source source , NotEvaluator notEval , ExpressionEvaluator innerEval , DriverContext driverContext )
227+ implements
228+ ExpressionEvaluator {
229+ @ Override
230+ public Block eval (Page page ) {
231+ return notEval .eval (page );
232+ }
233+
234+ @ Override
235+ // NotEvaluator is a final, generated class - create this record to override score method
236+ public DoubleBlock score (Page page , BlockFactory blockFactory ) {
237+ try (DoubleBlock scoreBlock = innerEval .score (page , blockFactory )) {
238+ DoubleVector scoreVector = scoreBlock .asVector ();
239+ DoubleVector .Builder result = blockFactory .newDoubleVectorFixedBuilder (page .getPositionCount ());
240+ // TODO We could optimize for constant vectors
241+ for (int i = 0 ; i < scoreVector .getPositionCount (); i ++) {
242+ result .appendDouble (scoreVector .getDouble (i ) == NO_MATCH_SCORE ? 0.0 : NO_MATCH_SCORE );
243+ }
244+ return result .build ().asBlock ();
245+ }
246+ }
247+
248+ @ Override
249+ public void close () {
250+ Releasables .closeExpectNoException (notEval , innerEval );
251+ }
252+ }
253+
254+ return driverContext -> {
255+ var expEval = toEvaluator (foldCtx , not .field (), layout , shardContexts , usesScoring );
256+ ExpressionEvaluator innerEval = expEval .get (driverContext );
257+ NotEvaluator notEvaluator = new NotEvaluator (not .source (), innerEval , driverContext );
258+ if (usesScoring ) {
259+ return new NotScoreEvaluator (not .source (), notEvaluator , innerEval , driverContext );
260+ }
261+ return notEvaluator ;
262+ };
219263 }
220264 }
221265
0 commit comments