Expose `simple_query_string` flags in `flags` parameter
This commit is contained in:
parent
602c63d2aa
commit
5463f7953f
|
@ -36,6 +36,9 @@ with default operator of `AND`, the same query is translated to
|
|||
|
||||
|`analyzer` |The analyzer used to analyze each term of the query when
|
||||
creating composite queries.
|
||||
|
||||
|`flags` |Flags specifying which features of the `simple_query_string` to
|
||||
enable. Defaults to `ALL`.
|
||||
|=======================================================================
|
||||
|
||||
[float]
|
||||
|
@ -76,3 +79,22 @@ introduced fields included). For example:
|
|||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
[float]
|
||||
==== Flags
|
||||
`simple_query_string` support multiple flags to specify which parsing features
|
||||
should be enabled. It is specified as a `|`-delimited string with the
|
||||
`flags` parameter:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
{
|
||||
"simple_query_string" : {
|
||||
"query" : "foo | bar & baz*",
|
||||
"flags" : "OR|AND|PREFIX"
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
The available flags are: `ALL`, `NONE`, `AND`, `OR`, `PREFIX`, `PHRASE`,
|
||||
`PRECEDENCE`, `ESCAPE`, and `WHITESPACE`.
|
|
@ -35,6 +35,7 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
private String analyzer;
|
||||
private Operator operator;
|
||||
private final String queryText;
|
||||
private int flags = -1;
|
||||
|
||||
/**
|
||||
* Operators for the default_operator
|
||||
|
@ -84,6 +85,22 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the enabled features of the SimpleQueryString.
|
||||
*/
|
||||
public SimpleQueryStringBuilder flags(SimpleQueryStringFlag... flags) {
|
||||
int value = 0;
|
||||
if (flags.length == 0) {
|
||||
value = SimpleQueryStringFlag.ALL.value;
|
||||
} else {
|
||||
for (SimpleQueryStringFlag flag : flags) {
|
||||
value |= flag.value;
|
||||
}
|
||||
}
|
||||
this.flags = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(SimpleQueryStringParser.NAME);
|
||||
|
@ -104,6 +121,10 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
builder.endArray();
|
||||
}
|
||||
|
||||
if (flags != -1) {
|
||||
builder.field("flags", flags);
|
||||
}
|
||||
|
||||
if (analyzer != null) {
|
||||
builder.field("analyzer", analyzer);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.queryparser.XSimpleQueryParser;
|
||||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Flags for the XSimpleQueryString parser
|
||||
*/
|
||||
public enum SimpleQueryStringFlag {
|
||||
ALL(-1),
|
||||
NONE(0),
|
||||
AND(XSimpleQueryParser.AND_OPERATOR),
|
||||
NOT(XSimpleQueryParser.NOT_OPERATOR),
|
||||
OR(XSimpleQueryParser.OR_OPERATOR),
|
||||
PREFIX(XSimpleQueryParser.PREFIX_OPERATOR),
|
||||
PRECEDENCE(XSimpleQueryParser.PRECEDENCE_OPERATORS),
|
||||
ESCAPE(XSimpleQueryParser.ESCAPE_OPERATOR),
|
||||
WHITESPACE(XSimpleQueryParser.WHITESPACE_OPERATOR);
|
||||
|
||||
final int value;
|
||||
|
||||
private SimpleQueryStringFlag(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
static int resolveFlags(String flags) {
|
||||
if (!Strings.hasLength(flags)) {
|
||||
return ALL.value();
|
||||
}
|
||||
int magic = NONE.value();
|
||||
for (String s : Strings.delimitedListToStringArray(flags, "|")) {
|
||||
if (s.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
SimpleQueryStringFlag flag = SimpleQueryStringFlag.valueOf(s.toUpperCase(Locale.ROOT));
|
||||
switch (flag) {
|
||||
case NONE:
|
||||
return 0;
|
||||
case ALL:
|
||||
return -1;
|
||||
default:
|
||||
magic |= flag.value();
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new ElasticSearchIllegalArgumentException("Unknown " + SimpleQueryStringParser.NAME + " flag [" + s + "]");
|
||||
}
|
||||
}
|
||||
return magic;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -86,6 +87,7 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
Map<String, Float> fieldsAndWeights = null;
|
||||
BooleanClause.Occur defaultOperator = null;
|
||||
Analyzer analyzer = null;
|
||||
int flags = -1;
|
||||
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
|
@ -146,6 +148,17 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
throw new QueryParsingException(parseContext.index(),
|
||||
"[" + NAME + "] default operator [" + op + "] is not allowed");
|
||||
}
|
||||
} else if ("flags".equals(currentFieldName)) {
|
||||
if (parser.hasTextCharacters()) {
|
||||
// Possible options are:
|
||||
// ALL, NONE, AND, OR, PREFIX, PHRASE, PRECEDENCE, ESCAPE, WHITESPACE
|
||||
flags = SimpleQueryStringFlag.resolveFlags(parser.text());
|
||||
} else {
|
||||
flags = parser.intValue();
|
||||
if (flags < 0) {
|
||||
flags = SimpleQueryStringFlag.ALL.value();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[" + NAME + "] unsupported field [" + parser.currentName() + "]");
|
||||
}
|
||||
|
@ -174,9 +187,9 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
|
||||
XSimpleQueryParser sqp;
|
||||
if (fieldsAndWeights != null) {
|
||||
sqp = new XSimpleQueryParser(analyzer, fieldsAndWeights);
|
||||
sqp = new XSimpleQueryParser(analyzer, fieldsAndWeights, flags);
|
||||
} else {
|
||||
sqp = new XSimpleQueryParser(analyzer, field);
|
||||
sqp = new XSimpleQueryParser(analyzer, Collections.singletonMap(field, 1.0F), flags);
|
||||
}
|
||||
|
||||
if (defaultOperator != null) {
|
||||
|
|
|
@ -1955,4 +1955,59 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
|
|||
assertFirstHit(searchResponse, hasId("5"));
|
||||
assertSearchHits(searchResponse, "5", "6");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleQueryStringFlags() {
|
||||
assertAcked(client().admin().indices().prepareCreate("test").setSettings(SETTING_NUMBER_OF_SHARDS, 1));
|
||||
client().prepareIndex("test", "type1", "1").setSource("body", "foo").get();
|
||||
client().prepareIndex("test", "type1", "2").setSource("body", "bar").get();
|
||||
client().prepareIndex("test", "type1", "3").setSource("body", "foo bar").get();
|
||||
client().prepareIndex("test", "type1", "4").setSource("body", "quux baz eggplant").get();
|
||||
client().prepareIndex("test", "type1", "5").setSource("body", "quux baz spaghetti").get();
|
||||
client().prepareIndex("test", "type1", "6").setSource("otherbody", "spaghetti").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch().setQuery(
|
||||
simpleQueryString("foo bar").flags(SimpleQueryStringFlag.ALL)).get();
|
||||
assertHitCount(searchResponse, 3l);
|
||||
assertSearchHits(searchResponse, "1", "2", "3");
|
||||
|
||||
searchResponse = client().prepareSearch().setQuery(
|
||||
simpleQueryString("foo | bar")
|
||||
.defaultOperator(SimpleQueryStringBuilder.Operator.AND)
|
||||
.flags(SimpleQueryStringFlag.OR)).get();
|
||||
assertHitCount(searchResponse, 3l);
|
||||
assertSearchHits(searchResponse, "1", "2", "3");
|
||||
|
||||
searchResponse = client().prepareSearch().setQuery(
|
||||
simpleQueryString("foo | bar")
|
||||
.defaultOperator(SimpleQueryStringBuilder.Operator.AND)
|
||||
.flags(SimpleQueryStringFlag.NONE)).get();
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertFirstHit(searchResponse, hasId("3"));
|
||||
|
||||
searchResponse = client().prepareSearch().setQuery(
|
||||
simpleQueryString("baz | egg*")
|
||||
.defaultOperator(SimpleQueryStringBuilder.Operator.AND)
|
||||
.flags(SimpleQueryStringFlag.NONE)).get();
|
||||
assertHitCount(searchResponse, 0l);
|
||||
|
||||
searchResponse = client().prepareSearch().setSource("{\n" +
|
||||
" \"query\": {\n" +
|
||||
" \"simple_query_string\": {\n" +
|
||||
" \"query\": \"foo|bar\",\n" +
|
||||
" \"default_operator\": \"AND\"," +
|
||||
" \"flags\": \"NONE\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}").get();
|
||||
assertHitCount(searchResponse, 1l);
|
||||
|
||||
searchResponse = client().prepareSearch().setQuery(
|
||||
simpleQueryString("baz | egg*")
|
||||
.defaultOperator(SimpleQueryStringBuilder.Operator.AND)
|
||||
.flags(SimpleQueryStringFlag.WHITESPACE, SimpleQueryStringFlag.PREFIX)).get();
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertFirstHit(searchResponse, hasId("4"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue