LUCENE-8908: return def val from objectVal when exists returns false

* This behavior is similar to floatVal in QueryValueSource
This commit is contained in:
Munendra S N 2020-03-18 10:39:31 +05:30
parent 2b327e5deb
commit 6a59d443bc
4 changed files with 48 additions and 6 deletions

View File

@ -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
---------------------

View File

@ -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

View File

@ -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 {

View File

@ -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();