LUCENE-6149: Infix suggesters' highlighting and allTermsRequired can be set at the constructor for non-contextual lookup

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1649893 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tomas Eduardo Fernandez Lobbe 2015-01-06 18:14:04 +00:00
parent 136174bc13
commit 3ab114bb5e
4 changed files with 107 additions and 6 deletions

View File

@ -343,6 +343,10 @@ API Changes
* LUCENE-6146: Replaced Directory.copy() with Directory.copyFrom().
(Robert Muir)
* LUCENE-6149: Infix suggesters' highlighting and allTermsRequired can
be set at the constructor for non-contextual lookup.
(Boon Low, Tomás Fernández Löbbe)
Bug Fixes
* LUCENE-5650: Enforce read-only access to any path outside the temporary

View File

@ -129,6 +129,10 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
protected final Analyzer indexAnalyzer;
private final Directory dir;
final int minPrefixChars;
private final boolean allTermsRequired;
private final boolean highlight;
private final boolean commitOnBuild;
/** Used for ongoing NRT additions/updates. */
@ -140,6 +144,12 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
/** Default minimum number of leading characters before
* PrefixQuery is used (4). */
public static final int DEFAULT_MIN_PREFIX_CHARS = 4;
/** Default boolean clause option for multiple terms matching (all terms required). */
public static final boolean DEFAULT_ALL_TERMS_REQUIRED = true;
/** Default higlighting option. */
public static final boolean DEFAULT_HIGHLIGHT = true;
/** How we sort the postings and search results. */
private static final Sort SORT = new Sort(new SortField("weight", SortField.Type.LONG, true));
@ -150,9 +160,9 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
* Lucene index). Note that {@link #close}
* will also close the provided directory. */
public AnalyzingInfixSuggester(Directory dir, Analyzer analyzer) throws IOException {
this(dir, analyzer, analyzer, DEFAULT_MIN_PREFIX_CHARS, false);
this(dir, analyzer, analyzer, DEFAULT_MIN_PREFIX_CHARS, false, DEFAULT_ALL_TERMS_REQUIRED, DEFAULT_HIGHLIGHT);
}
/** Create a new instance, loading from a previously built
* AnalyzingInfixSuggester directory, if it exists. This directory must be
* private to the infix suggester (i.e., not an external
@ -170,7 +180,32 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
*/
public AnalyzingInfixSuggester(Directory dir, Analyzer indexAnalyzer, Analyzer queryAnalyzer, int minPrefixChars,
boolean commitOnBuild) throws IOException {
this(dir, indexAnalyzer, queryAnalyzer, minPrefixChars, commitOnBuild, DEFAULT_ALL_TERMS_REQUIRED, DEFAULT_HIGHLIGHT);
}
/** Create a new instance, loading from a previously built
* AnalyzingInfixSuggester directory, if it exists. This directory must be
* private to the infix suggester (i.e., not an external
* Lucene index). Note that {@link #close}
* will also close the provided directory.
*
* @param minPrefixChars Minimum number of leading characters
* before PrefixQuery is used (default 4).
* Prefixes shorter than this are indexed as character
* ngrams (increasing index size but making lookups
* faster).
*
* @param commitOnBuild Call commit after the index has finished building. This would persist the
* suggester index to disk and future instances of this suggester can use this pre-built dictionary.
*
* @param allTermsRequired All terms in the suggest query must be matched.
* @param highlight Highlight suggest query in suggestions.
*
*/
public AnalyzingInfixSuggester(Directory dir, Analyzer indexAnalyzer, Analyzer queryAnalyzer, int minPrefixChars,
boolean commitOnBuild,
boolean allTermsRequired, boolean highlight) throws IOException {
if (minPrefixChars < 0) {
throw new IllegalArgumentException("minPrefixChars must be >= 0; got: " + minPrefixChars);
}
@ -180,6 +215,8 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
this.dir = dir;
this.minPrefixChars = minPrefixChars;
this.commitOnBuild = commitOnBuild;
this.allTermsRequired = allTermsRequired;
this.highlight = highlight;
if (DirectoryReader.indexExists(dir)) {
// Already built; open it:
@ -369,7 +406,7 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
@Override
public List<LookupResult> lookup(CharSequence key, Set<BytesRef> contexts, boolean onlyMorePopular, int num) throws IOException {
return lookup(key, contexts, num, true, true);
return lookup(key, contexts, num, allTermsRequired, highlight);
}
/** Lookup, without any context. */

View File

@ -117,7 +117,27 @@ public class BlendedInfixSuggester extends AnalyzingInfixSuggester {
this.blenderType = blenderType;
this.numFactor = numFactor;
}
/**
* Create a new instance, loading from a previously built
* directory, if it exists.
*
* @param blenderType Type of blending strategy, see BlenderType for more precisions
* @param numFactor Factor to multiply the number of searched elements before ponderate
* @param commitOnBuild Call commit after the index has finished building. This would persist the
* suggester index to disk and future instances of this suggester can use this pre-built dictionary.
* @param allTermsRequired All terms in the suggest query must be matched.
* @param highlight Highlight suggest query in suggestions.
* @throws IOException If there are problems opening the underlying Lucene index.
*/
public BlendedInfixSuggester(Directory dir, Analyzer indexAnalyzer, Analyzer queryAnalyzer,
int minPrefixChars, BlenderType blenderType, int numFactor,
boolean commitOnBuild, boolean allTermsRequired, boolean highlight) throws IOException {
super(dir, indexAnalyzer, queryAnalyzer, minPrefixChars, commitOnBuild, allTermsRequired, highlight);
this.blenderType = blenderType;
this.numFactor = numFactor;
}
@Override
public List<Lookup.LookupResult> lookup(CharSequence key, Set<BytesRef> contexts, boolean onlyMorePopular, int num) throws IOException {
// here we multiply the number of searched element by the defined factor

View File

@ -91,10 +91,50 @@ public class AnalyzingInfixSuggesterTest extends LuceneTestCase {
assertEquals("a <b>p</b>enny saved is a <b>p</b>enny earned", results.get(0).highlightKey);
assertEquals(10, results.get(0).value);
assertEquals(new BytesRef("foobaz"), results.get(0).payload);
results = suggester.lookup(TestUtil.stringToCharSequence("money penny", random()), 10, false, true);
assertEquals(1, results.size());
assertEquals("a penny saved is a penny earned", results.get(0).key);
assertEquals("a <b>penny</b> saved is a <b>penny</b> earned", results.get(0).highlightKey);
assertEquals(10, results.get(0).value);
assertEquals(new BytesRef("foobaz"), results.get(0).payload);
results = suggester.lookup(TestUtil.stringToCharSequence("penny ea", random()), 10, false, true);
assertEquals(2, results.size());
assertEquals("a penny saved is a penny earned", results.get(0).key);
assertEquals("a <b>penny</b> saved is a <b>penny</b> <b>ea</b>rned", results.get(0).highlightKey);
assertEquals("lend me your ear", results.get(1).key);
assertEquals("lend me your <b>ea</b>r", results.get(1).highlightKey);
results = suggester.lookup(TestUtil.stringToCharSequence("money penny", random()), 10, false, false);
assertEquals(1, results.size());
assertEquals("a penny saved is a penny earned", results.get(0).key);
assertNull(results.get(0).highlightKey);
testConstructorDefatuls(suggester, keys, a, true, true);
testConstructorDefatuls(suggester, keys, a, true, false);
testConstructorDefatuls(suggester, keys, a, false, false);
testConstructorDefatuls(suggester, keys, a, false, true);
suggester.close();
}
private void testConstructorDefatuls(AnalyzingInfixSuggester suggester, Input[] keys, Analyzer a,
boolean allTermsRequired, boolean highlight) throws IOException {
AnalyzingInfixSuggester suggester2 = new AnalyzingInfixSuggester(newDirectory(), a, a, 3, false, allTermsRequired, highlight);
suggester2.build(new InputArrayIterator(keys));
CharSequence key = TestUtil.stringToCharSequence("penny ea", random());
List<LookupResult> results1 = suggester.lookup(key, 10, allTermsRequired, highlight);
List<LookupResult> results2 = suggester2.lookup(key, false, 10);
assertEquals(results1.size(), results2.size());
assertEquals(results1.get(0).key, results2.get(0).key);
assertEquals(results1.get(0).highlightKey, results2.get(0).highlightKey);
suggester2.close();
}
public void testAfterLoad() throws Exception {
Input keys[] = new Input[] {
new Input("lend me your ear", 8, new BytesRef("foobar")),