You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2021/02/14 05:13:49 UTC
[lucene-solr] branch master updated: LUCENE-9762:
FunctionScoreQuery must guard score() called twice (#2358)
This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/master by this push:
new 6c140b6 LUCENE-9762: FunctionScoreQuery must guard score() called twice (#2358)
6c140b6 is described below
commit 6c140b6dcf3948c4e198ebfd5978673c621216ee
Author: David Smiley <ds...@apache.org>
AuthorDate: Sun Feb 14 00:13:23 2021 -0500
LUCENE-9762: FunctionScoreQuery must guard score() called twice (#2358)
The score() may be called multiple times. It should take care to call DoubleValues.advanceExact only the first time, or risk faulty behavior including exceptions.
---
.../queries/function/FunctionScoreQuery.java | 6 ++++-
.../queries/function/TestFunctionScoreQuery.java | 29 ++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
index aed12ff..a2750cc 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
@@ -234,9 +234,13 @@ public final class FunctionScoreQuery extends Query {
}
DoubleValues scores = valueSource.getValues(context, DoubleValuesSource.fromScorer(in));
return new FilterScorer(in) {
+ int scoresDocId = -1; // remember the last docId we called score() on
+
@Override
public float score() throws IOException {
- if (scores.advanceExact(docID())) {
+ int docId = docID();
+ if (scoresDocId == docId || scores.advanceExact(docId)) {
+ scoresDocId = docId;
double factor = scores.doubleValue();
if (factor >= 0) {
return (float) (factor * boost);
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
index 3450280..737ab70 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
@@ -20,13 +20,16 @@ package org.apache.lucene.queries.function;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.document.TextField;
import org.apache.lucene.expressions.Expression;
import org.apache.lucene.expressions.SimpleBindings;
import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@@ -35,6 +38,7 @@ import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryUtils;
import org.apache.lucene.search.ScoreMode;
@@ -332,4 +336,29 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
fq.createWeight(searcher, inputScoreMode, 1f);
assertEquals(expectedScoreMode, scoreModeInWeight.get());
}
+
+ /** The FunctionScoreQuery's Scorer score() is going to be called twice for the same doc. */
+ public void testScoreCalledTwice() throws Exception {
+ try (Directory dir = newDirectory()) {
+ IndexWriterConfig conf = newIndexWriterConfig();
+ IndexWriter indexWriter = new IndexWriter(dir, conf);
+ Document doc = new Document();
+ doc.add(new TextField("ExampleText", "periodic function", Field.Store.NO));
+ doc.add(new TextField("ExampleText", "plot of the original function", Field.Store.NO));
+ indexWriter.addDocument(doc);
+ indexWriter.commit();
+ indexWriter.close();
+
+ try (DirectoryReader reader = DirectoryReader.open(dir)) {
+ Query q = new TermQuery(new Term("ExampleText", "function"));
+
+ q =
+ FunctionScoreQuery.boostByQuery(
+ q, new PhraseQuery(1, "ExampleText", "function", "plot"), 2);
+ q = FunctionScoreQuery.boostByValue(q, DoubleValuesSource.SCORES);
+
+ assertEquals(1, new IndexSearcher(reader).search(q, 10).totalHits.value);
+ }
+ }
+ }
}