This commit removes the ability to use `filter` for PhraseSuggester collate.

Only `query` can be used for collation.

Internally, a collate query is executed as an exists query. So specifying a
filter does not have any benefits.
This commit is contained in:
Areek Zillur 2015-05-15 16:17:47 -04:00
parent 35a58d874e
commit fb8cd53582
6 changed files with 24 additions and 106 deletions

View File

@ -162,13 +162,13 @@ can contain misspellings (See parameter descriptions below).
is wrapped rather than each token. is wrapped rather than each token.
`collate`:: `collate`::
Checks each suggestion against the specified `query` or `filter` to Checks each suggestion against the specified `query` to prune suggestions
prune suggestions for which no matching docs exist in the index. for which no matching docs exist in the index. The collate query for a
The collate query for a suggestion is run only on the local shard from which suggestion is run only on the local shard from which the suggestion has
the suggestion has been generated from. Either a `query` or a `filter` must been generated from. The `query` must be specified, and it is run as
be specified, and it is run as a <<query-dsl-template-query,`template` query>>. a <<query-dsl-template-query,`template` query>>.
The current suggestion is automatically made available as the `{{suggestion}}` The current suggestion is automatically made available as the `{{suggestion}}`
variable, which should be used in your query/filter. You can still specify variable, which should be used in your query. You can still specify
your own template `params` -- the `suggestion` value will be added to the your own template `params` -- the `suggestion` value will be added to the
variables you specify. Additionally, you can specify a `prune` to control variables you specify. Additionally, you can specify a `prune` to control
if all phrase suggestions will be returned, when set to `true` the suggestions if all phrase suggestions will be returned, when set to `true` the suggestions

View File

@ -134,20 +134,13 @@ public final class PhraseSuggestParser implements SuggestContextParser {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) { if (token == XContentParser.Token.FIELD_NAME) {
fieldName = parser.currentName(); fieldName = parser.currentName();
} else if ("query".equals(fieldName) || "filter".equals(fieldName)) { } else if ("query".equals(fieldName)) {
Template template = Template.parse(parser);
if (suggestion.getCollateFilterScript() != null) {
throw new IllegalArgumentException("suggester[phrase][collate] filter already set, doesn't support additional [" + fieldName + "]");
}
if (suggestion.getCollateQueryScript() != null) { if (suggestion.getCollateQueryScript() != null) {
throw new IllegalArgumentException("suggester[phrase][collate] query already set, doesn't support additional [" + fieldName + "]"); throw new IllegalArgumentException("suggester[phrase][collate] query already set, doesn't support additional [" + fieldName + "]");
} }
Template template = Template.parse(parser);
CompiledScript compiledScript = suggester.scriptService().compile(template, ScriptContext.Standard.SEARCH); CompiledScript compiledScript = suggester.scriptService().compile(template, ScriptContext.Standard.SEARCH);
if ("query".equals(fieldName)) { suggestion.setCollateQueryScript(compiledScript);
suggestion.setCollateQueryScript(compiledScript);
} else {
suggestion.setCollateFilterScript(compiledScript);
}
} else if ("params".equals(fieldName)) { } else if ("params".equals(fieldName)) {
suggestion.setCollateScriptParams(parser.map()); suggestion.setCollateScriptParams(parser.map());
} else if ("prune".equals(fieldName)) { } else if ("prune".equals(fieldName)) {

View File

@ -34,7 +34,6 @@ import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.Lucene.EarlyTerminatingCollector; import org.elasticsearch.common.lucene.Lucene.EarlyTerminatingCollector;
import org.elasticsearch.common.text.StringText; import org.elasticsearch.common.text.StringText;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.ParsedQuery;
import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ExecutableScript;
@ -105,14 +104,7 @@ public final class PhraseSuggester extends Suggester<PhraseSuggestionContext> {
final BytesRefBuilder byteSpare = new BytesRefBuilder(); final BytesRefBuilder byteSpare = new BytesRefBuilder();
final EarlyTerminatingCollector collector = Lucene.createExistsCollector(); final EarlyTerminatingCollector collector = Lucene.createExistsCollector();
final CompiledScript collateScript; final CompiledScript collateScript = suggestion.getCollateQueryScript();
if (suggestion.getCollateQueryScript() != null) {
collateScript = suggestion.getCollateQueryScript();
} else if (suggestion.getCollateFilterScript() != null) {
collateScript = suggestion.getCollateFilterScript();
} else {
collateScript = null;
}
final boolean collatePrune = (collateScript != null) && suggestion.collatePrune(); final boolean collatePrune = (collateScript != null) && suggestion.collatePrune();
for (int i = 0; i < checkerResult.corrections.length; i++) { for (int i = 0; i < checkerResult.corrections.length; i++) {
Correction correction = checkerResult.corrections[i]; Correction correction = checkerResult.corrections[i];
@ -125,13 +117,7 @@ public final class PhraseSuggester extends Suggester<PhraseSuggestionContext> {
vars.put(SUGGESTION_TEMPLATE_VAR_NAME, spare.toString()); vars.put(SUGGESTION_TEMPLATE_VAR_NAME, spare.toString());
final ExecutableScript executable = scriptService.executable(collateScript, vars); final ExecutableScript executable = scriptService.executable(collateScript, vars);
final BytesReference querySource = (BytesReference) executable.run(); final BytesReference querySource = (BytesReference) executable.run();
final ParsedQuery parsedQuery; final ParsedQuery parsedQuery = suggestion.getQueryParserService().parse(querySource);
if (suggestion.getCollateFilterScript() != null) {
parsedQuery = suggestion.getQueryParserService().parse(
QueryBuilders.constantScoreQuery(QueryBuilders.wrapperQuery(querySource)));
} else {
parsedQuery = suggestion.getQueryParserService().parse(querySource);
}
collateMatch = Lucene.exists(searcher, parsedQuery.query(), collector); collateMatch = Lucene.exists(searcher, parsedQuery.query(), collector);
} }
if (!collateMatch && !collatePrune) { if (!collateMatch && !collatePrune) {

View File

@ -42,8 +42,6 @@ public final class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSugge
private String preTag; private String preTag;
private String postTag; private String postTag;
private String collateQuery; private String collateQuery;
private String collateFilter;
private String collatePreference;
private Map<String, Object> collateParams; private Map<String, Object> collateParams;
private Boolean collatePrune; private Boolean collatePrune;
@ -178,22 +176,6 @@ public final class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSugge
return this; return this;
} }
/**
* Sets a filter used for filtering out suggested phrases (collation).
*/
public PhraseSuggestionBuilder collateFilter(String collateFilter) {
this.collateFilter = collateFilter;
return this;
}
/**
* Sets routing preferences for executing filter query (collation).
*/
public PhraseSuggestionBuilder collatePreference(String collatePreference) {
this.collatePreference = collatePreference;
return this;
}
/** /**
* Sets additional params for collate script * Sets additional params for collate script
*/ */
@ -254,17 +236,9 @@ public final class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSugge
builder.field("post_tag", postTag); builder.field("post_tag", postTag);
builder.endObject(); builder.endObject();
} }
if (collateQuery != null || collateFilter != null) { if (collateQuery != null) {
builder.startObject("collate"); builder.startObject("collate");
if (collateQuery != null) { builder.field("query", collateQuery);
builder.field("query", collateQuery);
}
if (collateFilter != null) {
builder.field("filter", collateFilter);
}
if (collatePreference != null) {
builder.field("preference", collatePreference);
}
if (collateParams != null) { if (collateParams != null) {
builder.field("params", collateParams); builder.field("params", collateParams);
} }

View File

@ -204,14 +204,6 @@ class PhraseSuggestionContext extends SuggestionContext {
this.collateQueryScript = collateQueryScript; this.collateQueryScript = collateQueryScript;
} }
CompiledScript getCollateFilterScript() {
return collateFilterScript;
}
void setCollateFilterScript(CompiledScript collateFilterScript) {
this.collateFilterScript = collateFilterScript;
}
Map<String, Object> getCollateScriptParams() { Map<String, Object> getCollateScriptParams() {
return collateScriptParams; return collateScriptParams;
} }

View File

@ -1129,7 +1129,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
} }
indexRandom(true, builders); indexRandom(true, builders);
// suggest without filtering // suggest without collate
PhraseSuggestionBuilder suggest = phraseSuggestion("title") PhraseSuggestionBuilder suggest = phraseSuggestion("title")
.field("title") .field("title")
.addCandidateGenerator(PhraseSuggestionBuilder.candidateGenerator("title") .addCandidateGenerator(PhraseSuggestionBuilder.candidateGenerator("title")
@ -1145,7 +1145,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
Suggest searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", suggest); Suggest searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", suggest);
assertSuggestionSize(searchSuggest, 0, 10, "title"); assertSuggestionSize(searchSuggest, 0, 10, "title");
// suggest with filtering // suggest with collate
String filterString = XContentFactory.jsonBuilder() String filterString = XContentFactory.jsonBuilder()
.startObject() .startObject()
.startObject("match_phrase") .startObject("match_phrase")
@ -1157,13 +1157,13 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", filteredQuerySuggest); searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", filteredQuerySuggest);
assertSuggestionSize(searchSuggest, 0, 2, "title"); assertSuggestionSize(searchSuggest, 0, 2, "title");
// filtered suggest with no result (boundary case) // collate suggest with no result (boundary case)
searchSuggest = searchSuggest("Elections of Representatives Parliament", filteredQuerySuggest); searchSuggest = searchSuggest("Elections of Representatives Parliament", filteredQuerySuggest);
assertSuggestionSize(searchSuggest, 0, 0, "title"); assertSuggestionSize(searchSuggest, 0, 0, "title");
NumShards numShards = getNumShards("test"); NumShards numShards = getNumShards("test");
// filtered suggest with bad query // collate suggest with bad query
String incorrectFilterString = XContentFactory.jsonBuilder() String incorrectFilterString = XContentFactory.jsonBuilder()
.startObject() .startObject()
.startObject("test") .startObject("test")
@ -1179,7 +1179,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
// expected // expected
} }
// suggest with filter collation // suggest with collation
String filterStringAsFilter = XContentFactory.jsonBuilder() String filterStringAsFilter = XContentFactory.jsonBuilder()
.startObject() .startObject()
.startObject("query") .startObject("query")
@ -1190,11 +1190,11 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.endObject() .endObject()
.string(); .string();
PhraseSuggestionBuilder filteredFilterSuggest = suggest.collateQuery(null).collateFilter(filterStringAsFilter); PhraseSuggestionBuilder filteredFilterSuggest = suggest.collateQuery(filterStringAsFilter);
searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", filteredFilterSuggest); searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", filteredFilterSuggest);
assertSuggestionSize(searchSuggest, 0, 2, "title"); assertSuggestionSize(searchSuggest, 0, 2, "title");
// filtered suggest with bad filter // collate suggest with bad query
String filterStr = XContentFactory.jsonBuilder() String filterStr = XContentFactory.jsonBuilder()
.startObject() .startObject()
.startObject("pprefix") .startObject("pprefix")
@ -1203,7 +1203,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.endObject() .endObject()
.string(); .string();
PhraseSuggestionBuilder in = suggest.collateQuery(null).collateFilter(filterStr); PhraseSuggestionBuilder in = suggest.collateQuery(filterStr);
try { try {
searchSuggest("united states house of representatives elections in washington 2006", numShards.numPrimaries, in); searchSuggest("united states house of representatives elections in washington 2006", numShards.numPrimaries, in);
fail("Post filter error has been swallowed"); fail("Post filter error has been swallowed");
@ -1221,7 +1221,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.string(); .string();
PhraseSuggestionBuilder phraseSuggestWithNoParams = suggest.collateFilter(null).collateQuery(collateWithParams); PhraseSuggestionBuilder phraseSuggestWithNoParams = suggest.collateQuery(collateWithParams);
try { try {
searchSuggest("united states house of representatives elections in washington 2006", numShards.numPrimaries, phraseSuggestWithNoParams); searchSuggest("united states house of representatives elections in washington 2006", numShards.numPrimaries, phraseSuggestWithNoParams);
fail("Malformed query (lack of additional params) should fail"); fail("Malformed query (lack of additional params) should fail");
@ -1234,39 +1234,12 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
params.put("query_type", "match_phrase"); params.put("query_type", "match_phrase");
params.put("query_field", "title"); params.put("query_field", "title");
PhraseSuggestionBuilder phraseSuggestWithParams = suggest.collateFilter(null).collateQuery(collateWithParams).collateParams(params); PhraseSuggestionBuilder phraseSuggestWithParams = suggest.collateQuery(collateWithParams).collateParams(params);
searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", phraseSuggestWithParams); searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", phraseSuggestWithParams);
assertSuggestionSize(searchSuggest, 0, 2, "title"); assertSuggestionSize(searchSuggest, 0, 2, "title");
//collate request defining both query/filter should fail
PhraseSuggestionBuilder phraseSuggestWithFilterAndQuery = suggest.collateFilter(filterStringAsFilter).collateQuery(filterString);
try {
searchSuggest("united states house of representatives elections in washington 2006", numShards.numPrimaries, phraseSuggestWithFilterAndQuery);
fail("expected parse failure, as both filter and query are set in collate");
} catch (ElasticsearchException e) {
// expected
}
// collate query request with prune set to true // collate query request with prune set to true
PhraseSuggestionBuilder phraseSuggestWithParamsAndReturn = suggest.collateFilter(null).collateQuery(collateWithParams).collateParams(params).collatePrune(true); PhraseSuggestionBuilder phraseSuggestWithParamsAndReturn = suggest.collateQuery(collateWithParams).collateParams(params).collatePrune(true);
searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", phraseSuggestWithParamsAndReturn);
assertSuggestionSize(searchSuggest, 0, 10, "title");
assertSuggestionPhraseCollateMatchExists(searchSuggest, "title", 2);
collateWithParams = XContentFactory.jsonBuilder()
.startObject()
.startObject("query")
.startObject("{{query_type}}")
.field("{{query_field}}", "{{suggestion}}")
.endObject()
.endObject()
.endObject().string();
params.clear();
params.put("query_type", "match_phrase");
params.put("query_field", "title");
// collate filter request with prune set to true
phraseSuggestWithParamsAndReturn = suggest.collateFilter(collateWithParams).collateQuery(null).collateParams(params).collatePrune(true);
searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", phraseSuggestWithParamsAndReturn); searchSuggest = searchSuggest("united states house of representatives elections in washington 2006", phraseSuggestWithParamsAndReturn);
assertSuggestionSize(searchSuggest, 0, 10, "title"); assertSuggestionSize(searchSuggest, 0, 10, "title");
assertSuggestionPhraseCollateMatchExists(searchSuggest, "title", 2); assertSuggestionPhraseCollateMatchExists(searchSuggest, "title", 2);