diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index c6bb4591305..195da2ec5ff 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -139,6 +139,9 @@ Bug Fixes * LUCENE-9164: Ensure IW processes all internal events before it closes itself on a rollback. (Simon Willnauer, Nhat Nguyen, Dawid Weiss, Mike Mccandless) +* LUCENE-8908: Return default value from objectVal when doc doesn't match the query in QueryValueSource + (Bill Bell, hossman, Munendra S N, Michele Palmia) + Other --------------------- diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java index 55cf2cbf905..81d3bbaaf34 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java @@ -166,11 +166,7 @@ class QueryDocValues extends FloatDocValues { @Override public Object objectVal(int doc) { - try { - return exists(doc) ? scorer.score() : null; - } catch (IOException e) { - throw new RuntimeException("caught exception in QueryDocVals(" + q + ") doc=" + doc, e); - } + return floatVal(doc); } @Override diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java index 415692fcf44..a75cc66219e 100644 --- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java +++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java @@ -41,6 +41,7 @@ import org.apache.lucene.queries.function.valuesource.*; import org.apache.lucene.search.CheckHits; import org.apache.lucene.search.DoubleValuesSource; import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.ScoreMode; @@ -424,6 +425,16 @@ public class TestValueSources extends LuceneTestCase { vs = new QueryValueSource(new TermQuery(new Term("bogus","does not exist")), 0F); assertNoneExist(vs); + // doc doesn't match the query, so default value should be returned + vs = new QueryValueSource(new MatchNoDocsQuery(), 5.0f); + final LeafReaderContext leaf = searcher.getIndexReader().leaves().get(0); + FunctionValues fv = vs.getValues(ValueSource.newContext(searcher), leaf); + assertEquals(5.0f, fv.objectVal(1)); + + // test with def value but doc matches the query, so def value shouldn't be returned + vs = new QueryValueSource(new TermQuery(new Term("text","test")), 2F); + fv = vs.getValues(ValueSource.newContext(searcher), leaf); + assertNotEquals(2f, fv.objectVal(1)); } finally { searcher.setSimilarity(saved); } @@ -516,7 +527,7 @@ public class TestValueSources extends LuceneTestCase { assertEquals("test(const(4.1),const(1.2),double(some_double)=0.0)", fv.toString(1)); } - + public void testTF() throws Exception { Similarity saved = searcher.getSimilarity(); try { diff --git a/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java b/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java index cf6b5c0e9e4..aa36d5a3cbc 100644 --- a/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java +++ b/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java @@ -1039,6 +1039,38 @@ public class TestFunctionQuery extends SolrTestCaseJ4 { /*id*/1, /*score*/2); } + @Test + public void testQueryAsFlParam() { + clearIndex(); + + assertU(adoc("id", "1", "age_i", "35")); + assertU(adoc("id", "2", "age_i", "25")); + assertU(commit()); + + // some docs match the query func but some doesn't + // if doc doesn't match, it should use default value + assertQ(req("q", "*:*", "fl", "*,score,bleh:query($qq,5.0)", "qq", "id:2"), + "//*[@numFound='2']", + "//result/doc[1]/str[@name='id'][.='1']", + "//result/doc[2]/str[@name='id'][.='2']", + "//result/doc[1]/float[@name='bleh'][.='5.0']", + "count(//result/doc[2]/float[@name='bleh'][.='5.0'])=0", + "//result/doc[2]/float[@name='bleh']" // since score can't be known, doing existing match + ); + + // when the doc match the query func condition default value shouldn't be used + // when no def val is passed in query func, 0.0 would be used + assertQ(req("q", "*:*", "fl", "*,score,bleh:query($qq)", "qq", "id:*"), + "//*[@numFound='2']", + "//result/doc[1]/str[@name='id'][.='1']", + "//result/doc[2]/str[@name='id'][.='2']", + "count(//result/doc[1]/float[@name='bleh'][.='0.0'])=0", + "count(//result/doc[2]/float[@name='bleh'][.='0.0'])=0", + "//result/doc[1]/float[@name='bleh']", + "//result/doc[2]/float[@name='bleh']" + ); + } + @Test public void testEqualFunction() { clearIndex();