-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Phrase Suggester: Add option to filter out phrase suggestions #6773
Changes from 12 commits
535f68c
f3d38df
ceac6ec
2693624
6181d83
902763b
be328f8
b4533aa
0d7cafe
359691d
f23712e
d6e1f07
5df71bb
b4a905d
beea2ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -167,14 +167,16 @@ private ShardIterator preferenceActiveShardIterator(IndexShardRoutingTable index | |
} | ||
} | ||
if (preference.charAt(0) == '_') { | ||
if (preference.startsWith("_shards:")) { | ||
Preference preferenceType = Preference.parse(preference); | ||
if (preferenceType == Preference.SHARDS) { | ||
// starts with _shards, so execute on specific ones | ||
int index = preference.indexOf(';'); | ||
|
||
String shards; | ||
if (index == -1) { | ||
shards = preference.substring("_shards:".length()); | ||
shards = preference.substring(Preference.SHARDS.type().length() + 1); | ||
} else { | ||
shards = preference.substring("_shards:".length(), index); | ||
shards = preference.substring(Preference.SHARDS.type().length() + 1, index); | ||
} | ||
String[] ids = Strings.splitStringByCommaToArray(shards); | ||
boolean found = false; | ||
|
@@ -200,23 +202,24 @@ private ShardIterator preferenceActiveShardIterator(IndexShardRoutingTable index | |
preference = preference.substring(index + 1); | ||
} | ||
} | ||
if (preference.startsWith("_prefer_node:")) { | ||
return indexShard.preferNodeActiveInitializingShardsIt(preference.substring("_prefer_node:".length())); | ||
preferenceType = Preference.parse(preference); | ||
if (preferenceType == Preference.PREFER_NODE) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think now that we have an enum we should just use a switch / case statement here? |
||
return indexShard.preferNodeActiveInitializingShardsIt(preference.substring(Preference.PREFER_NODE.type().length() + 1)); | ||
} | ||
if ("_local".equals(preference)) { | ||
if (preferenceType == Preference.LOCAL) { | ||
return indexShard.preferNodeActiveInitializingShardsIt(localNodeId); | ||
} | ||
if ("_primary".equals(preference)) { | ||
if (preferenceType == Preference.PRIMARY) { | ||
return indexShard.primaryActiveInitializingShardIt(); | ||
} | ||
if ("_primary_first".equals(preference) || "_primaryFirst".equals(preference)) { | ||
if (preferenceType == Preference.PRIMARY_FIRST) { | ||
return indexShard.primaryFirstActiveInitializingShardsIt(); | ||
} | ||
if ("_only_local".equals(preference) || "_onlyLocal".equals(preference)) { | ||
if (preferenceType == Preference.ONLY_LOCAL) { | ||
return indexShard.onlyNodeActiveInitializingShardsIt(localNodeId); | ||
} | ||
if (preference.startsWith("_only_node:")) { | ||
String nodeId = preference.substring("_only_node:".length()); | ||
if (preferenceType == Preference.ONLY_NODE) { | ||
String nodeId = preference.substring(Preference.ONLY_NODE.type().length() + 1); | ||
ensureNodeIdExists(nodes, nodeId); | ||
return indexShard.onlyNodeActiveInitializingShardsIt(nodeId); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
package org.elasticsearch.cluster.routing.operation.plain; | ||
|
||
import org.elasticsearch.ElasticsearchIllegalArgumentException; | ||
import org.elasticsearch.common.collect.Tuple; | ||
|
||
/** | ||
* Routing Preference Type | ||
*/ | ||
public enum Preference { | ||
|
||
/** | ||
* Route to specific shards | ||
*/ | ||
SHARDS("_shards"), | ||
|
||
/** | ||
* Route to preferred node, if possible | ||
*/ | ||
PREFER_NODE("_prefer_node"), | ||
|
||
/** | ||
* Route to local node, if possible | ||
*/ | ||
LOCAL("_local"), | ||
|
||
/** | ||
* Route to primary shards | ||
*/ | ||
PRIMARY("_primary"), | ||
|
||
/** | ||
* Route to primary shards first | ||
*/ | ||
PRIMARY_FIRST("_primary_first"), | ||
|
||
/** | ||
* Route to the local shard only | ||
*/ | ||
ONLY_LOCAL("_only_local"), | ||
|
||
/** | ||
* Route to specific node only | ||
*/ | ||
ONLY_NODE("_only_node"); | ||
|
||
private final String type; | ||
|
||
Preference(String type) { | ||
this.type = type; | ||
} | ||
|
||
public String type() { | ||
return type; | ||
} | ||
/** | ||
* Parses the Preference Type given a string | ||
*/ | ||
public static Preference parse(String preference) { | ||
String preferenceType; | ||
int colonIndex = preference.indexOf(':'); | ||
if (colonIndex == -1) { | ||
preferenceType = preference; | ||
} else { | ||
preferenceType = preference.substring(0, colonIndex); | ||
} | ||
|
||
switch (preferenceType) { | ||
case "_shards": | ||
return SHARDS; | ||
case "_prefer_node": | ||
return PREFER_NODE; | ||
case "_only_node": | ||
return ONLY_NODE; | ||
case "_local": | ||
return LOCAL; | ||
case "_primary": | ||
return PRIMARY; | ||
case "_primary_first": | ||
case "_primaryFirst": | ||
return PRIMARY_FIRST; | ||
case "_only_local": | ||
case "_onlyLocal": | ||
return ONLY_LOCAL; | ||
} | ||
throw new ElasticsearchIllegalArgumentException("no Preference for [" + preferenceType + "]"); | ||
} | ||
} | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.index.query; | ||
|
||
import org.elasticsearch.common.bytes.BytesReference; | ||
import org.elasticsearch.common.xcontent.*; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* FilterBuilder that constructs filters from {@link org.elasticsearch.common.bytes.BytesReference} | ||
* source | ||
*/ | ||
public class BytesFilterBuilder extends BaseFilterBuilder { | ||
|
||
private final BytesReference source; | ||
|
||
public BytesFilterBuilder(BytesReference source) { | ||
this.source = source; | ||
|
||
} | ||
|
||
@Override | ||
protected void doXContent(XContentBuilder builder, Params params) throws IOException { | ||
try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) { | ||
// unwrap the first layer of json dictionary | ||
parser.nextToken(); | ||
parser.nextToken(); | ||
builder.copyCurrentStructure(parser); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,10 +23,12 @@ | |
import org.apache.lucene.index.Terms; | ||
import org.apache.lucene.util.BytesRef; | ||
import org.elasticsearch.ElasticsearchIllegalArgumentException; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.elasticsearch.common.xcontent.XContentParser.Token; | ||
import org.elasticsearch.index.analysis.ShingleTokenFilterFactory; | ||
import org.elasticsearch.index.mapper.MapperService; | ||
import org.elasticsearch.script.CompiledScript; | ||
import org.elasticsearch.search.suggest.SuggestContextParser; | ||
import org.elasticsearch.search.suggest.SuggestUtils; | ||
import org.elasticsearch.search.suggest.SuggestionSearchContext; | ||
|
@@ -124,6 +126,43 @@ public SuggestionSearchContext.SuggestionContext parse(XContentParser parser, Ma | |
} | ||
} | ||
} | ||
} else if ("collate".equals(fieldName)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make sure you fire up an exception if both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added exceptions, before this was made impossible by |
||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { | ||
if (token == XContentParser.Token.FIELD_NAME) { | ||
fieldName = parser.currentName(); | ||
} else if ("query".equals(fieldName) || "filter".equals(fieldName)) { | ||
String templateNameOrTemplateContent; | ||
if (token == XContentParser.Token.START_OBJECT && !parser.hasTextCharacters()) { | ||
XContentBuilder builder = XContentBuilder.builder(parser.contentType().xContent()); | ||
builder.copyCurrentStructure(parser); | ||
templateNameOrTemplateContent = builder.string(); | ||
} else { | ||
templateNameOrTemplateContent = parser.text(); | ||
} | ||
if (templateNameOrTemplateContent == null) { | ||
throw new ElasticsearchIllegalArgumentException("suggester[phrase][collate] no query/filter found in collate object"); | ||
} | ||
if (suggestion.getCollateFilterScript() != null) { | ||
throw new ElasticsearchIllegalArgumentException("suggester[phrase][collate] filter already set, doesn't support additional [" + fieldName + "]"); | ||
} | ||
if (suggestion.getCollateQueryScript() != null) { | ||
throw new ElasticsearchIllegalArgumentException("suggester[phrase][collate] query already set, doesn't support additional [" + fieldName + "]"); | ||
} | ||
CompiledScript compiledScript = suggester.scriptService().compile("mustache", templateNameOrTemplateContent); | ||
if ("query".equals(fieldName)) { | ||
suggestion.setCollateQueryScript(compiledScript); | ||
} else { | ||
suggestion.setCollateFilterScript(compiledScript); | ||
} | ||
} else if ("preference".equals(fieldName)) { | ||
suggestion.setPreference(parser.text()); | ||
} else if ("params".equals(fieldName)) { | ||
suggestion.setCollateScriptParams(parser.map()); | ||
} else { | ||
throw new ElasticsearchIllegalArgumentException( | ||
"suggester[phrase][collate] doesn't support field [" + fieldName + "]"); | ||
} | ||
} | ||
} else { | ||
throw new ElasticsearchIllegalArgumentException("suggester[phrase] doesn't support array field [" + fieldName + "]"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a suggestion to make the docs slightly easier to read:
I also removed most of the options from the suggest request which are not relevant to
collate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @clintongormley, I have updated the docs