LUCENE-7505: AnalyzingInfixSuggester returned invalid results when allTermsRequired is false and context filters are specified

This commit is contained in:
Mike McCandless 2016-10-19 09:44:08 -04:00
parent c2e031add3
commit 45ca4bd3ed
3 changed files with 89 additions and 3 deletions

View File

@ -92,6 +92,10 @@ Bug Fixes
* LUCENE-7493: FacetCollector.search threw an unexpected exception if * LUCENE-7493: FacetCollector.search threw an unexpected exception if
you asked for zero hits but wanted facets (Mahesh via Mike McCandless) you asked for zero hits but wanted facets (Mahesh via Mike McCandless)
* LUCENE-7505: AnalyzingInfixSuggester returned invalid results when
allTermsRequired is false and context filters are specified (Mike
McCandless)
Improvements Improvements
* LUCENE-7439: FuzzyQuery now matches all terms within the specified * LUCENE-7439: FuzzyQuery now matches all terms within the specified

View File

@ -560,10 +560,16 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
} }
if (allMustNot) { if (allMustNot) {
//all are MUST_NOT: add the contextQuery to the main query instead (not as sub-query) // All are MUST_NOT: add the contextQuery to the main query instead (not as sub-query)
for (BooleanClause clause : contextQuery.clauses()) { for (BooleanClause clause : contextQuery.clauses()) {
query.add(clause); query.add(clause);
} }
} else if (allTermsRequired == false) {
// We must carefully upgrade the query clauses to MUST:
BooleanQuery.Builder newQuery = new BooleanQuery.Builder();
newQuery.add(query.build(), BooleanClause.Occur.MUST);
newQuery.add(contextQuery, BooleanClause.Occur.MUST);
query = newQuery;
} else { } else {
// Add contextQuery as sub-query // Add contextQuery as sub-query
query.add(contextQuery, BooleanClause.Occur.MUST); query.add(contextQuery, BooleanClause.Occur.MUST);
@ -577,7 +583,7 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
Query finalQuery = finishQuery(query, allTermsRequired); Query finalQuery = finishQuery(query, allTermsRequired);
//System.out.println("finalQuery=" + query); //System.out.println("finalQuery=" + finalQuery);
// Sort by weight, descending: // Sort by weight, descending:
TopFieldCollector c = TopFieldCollector.create(SORT, num, true, false, false); TopFieldCollector c = TopFieldCollector.create(SORT, num, true, false, false);

View File

@ -1258,4 +1258,80 @@ public class AnalyzingInfixSuggesterTest extends LuceneTestCase {
a.close(); a.close();
} }
} }
public void testContextNotAllTermsRequired() throws Exception {
Input keys[] = new Input[] {
new Input("lend me your ear", 8, new BytesRef("foobar"), asSet("foo", "bar")),
new Input("a penny saved is a penny earned", 10, new BytesRef("foobaz"), asSet("foo", "baz"))
};
Path tempDir = createTempDir("analyzingInfixContext");
Analyzer a = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false);
AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester(newFSDirectory(tempDir), a, a, 3, false);
suggester.build(new InputArrayIterator(keys));
// No context provided, all results returned
List<LookupResult> results = suggester.lookup(TestUtil.stringToCharSequence("ear", random()), 10, false, true);
assertEquals(2, results.size());
LookupResult result = results.get(0);
assertEquals("a penny saved is a penny earned", result.key);
assertEquals("a penny saved is a penny <b>ear</b>ned", result.highlightKey);
assertEquals(10, result.value);
assertEquals(new BytesRef("foobaz"), result.payload);
assertNotNull(result.contexts);
assertEquals(2, result.contexts.size());
assertTrue(result.contexts.contains(new BytesRef("foo")));
assertTrue(result.contexts.contains(new BytesRef("baz")));
result = results.get(1);
assertEquals("lend me your ear", result.key);
assertEquals("lend me your <b>ear</b>", result.highlightKey);
assertEquals(8, result.value);
assertEquals(new BytesRef("foobar"), result.payload);
assertNotNull(result.contexts);
assertEquals(2, result.contexts.size());
assertTrue(result.contexts.contains(new BytesRef("foo")));
assertTrue(result.contexts.contains(new BytesRef("bar")));
// Both have "foo" context:
results = suggester.lookup(TestUtil.stringToCharSequence("ear", random()), asSet("foo"), 10, false, true);
assertEquals(2, results.size());
result = results.get(0);
assertEquals("a penny saved is a penny earned", result.key);
assertEquals("a penny saved is a penny <b>ear</b>ned", result.highlightKey);
assertEquals(10, result.value);
assertEquals(new BytesRef("foobaz"), result.payload);
assertNotNull(result.contexts);
assertEquals(2, result.contexts.size());
assertTrue(result.contexts.contains(new BytesRef("foo")));
assertTrue(result.contexts.contains(new BytesRef("baz")));
result = results.get(1);
assertEquals("lend me your ear", result.key);
assertEquals("lend me your <b>ear</b>", result.highlightKey);
assertEquals(8, result.value);
assertEquals(new BytesRef("foobar"), result.payload);
assertNotNull(result.contexts);
assertEquals(2, result.contexts.size());
assertTrue(result.contexts.contains(new BytesRef("foo")));
assertTrue(result.contexts.contains(new BytesRef("bar")));
// Only one has "foo" context and len
results = suggester.lookup(TestUtil.stringToCharSequence("len", random()), asSet("foo"), 10, false, true);
assertEquals(1, results.size());
result = results.get(0);
assertEquals("lend me your ear", result.key);
assertEquals("<b>len</b>d me your ear", result.highlightKey);
assertEquals(8, result.value);
assertEquals(new BytesRef("foobar"), result.payload);
assertNotNull(result.contexts);
assertEquals(2, result.contexts.size());
assertTrue(result.contexts.contains(new BytesRef("foo")));
assertTrue(result.contexts.contains(new BytesRef("bar")));
suggester.close();
}
} }