mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-25 09:28:27 +00:00
Merge remote-tracking branch 'dakrone/sqs-all-field-mode'
This commit is contained in:
commit
2674e415c8
@ -119,7 +119,7 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
||||
private static final ParseField ALL_FIELDS_FIELD = new ParseField("all_fields");
|
||||
|
||||
// Mapping types the "all-ish" query can be executed against
|
||||
private static final Set<String> ALLOWED_QUERY_MAPPER_TYPES;
|
||||
public static final Set<String> ALLOWED_QUERY_MAPPER_TYPES;
|
||||
|
||||
static {
|
||||
ALLOWED_QUERY_MAPPER_TYPES = new HashSet<>();
|
||||
@ -908,7 +908,11 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
||||
timeZone == null ? 0 : timeZone.getID(), escape, maxDeterminizedStates, splitOnWhitespace, useAllFields);
|
||||
}
|
||||
|
||||
private Map<String, Float> allQueryableDefaultFields(QueryShardContext context) {
|
||||
/**
|
||||
* Given a shard context, return a map of all fields in the mappings that
|
||||
* can be queried. The map will be field name to a float of 1.0f.
|
||||
*/
|
||||
public static Map<String, Float> allQueryableDefaultFields(QueryShardContext context) {
|
||||
Collection<String> allFields = context.simpleMatchToIndexNames("*");
|
||||
Map<String, Float> fields = new HashMap<>();
|
||||
for (String fieldName : allFields) {
|
||||
@ -943,6 +947,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
||||
|
||||
Map<String, Float> resolvedFields = new TreeMap<>();
|
||||
|
||||
if ((useAllFields != null && useAllFields) && (fieldsAndWeights.size() != 0 || this.defaultField != null)) {
|
||||
throw addValidationError("cannot use [all_fields] parameter in conjunction with [default_field] or [fields]", null);
|
||||
}
|
||||
|
||||
// If explicitly required to use all fields, use all fields, OR:
|
||||
// Automatically determine the fields (to replace the _all field) if all of the following are true:
|
||||
// - The _all field is disabled,
|
||||
|
@ -270,6 +270,12 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
|
||||
public Settings() {
|
||||
}
|
||||
|
||||
public Settings(Settings other) {
|
||||
this.lenient = other.lenient;
|
||||
this.analyzeWildcard = other.analyzeWildcard;
|
||||
this.quoteFieldSuffix = other.quoteFieldSuffix;
|
||||
}
|
||||
|
||||
/** Specifies whether to use lenient parsing, defaults to false. */
|
||||
public void lenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
|
@ -106,6 +106,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
private static final ParseField QUERY_FIELD = new ParseField("query");
|
||||
private static final ParseField FIELDS_FIELD = new ParseField("fields");
|
||||
private static final ParseField QUOTE_FIELD_SUFFIX_FIELD = new ParseField("quote_field_suffix");
|
||||
private static final ParseField ALL_FIELDS_FIELD = new ParseField("all_fields");
|
||||
|
||||
/** Query text to parse. */
|
||||
private final String queryText;
|
||||
@ -126,6 +127,8 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
private String minimumShouldMatch;
|
||||
/** Any search flags to be used, ALL by default. */
|
||||
private int flags = DEFAULT_FLAGS;
|
||||
/** Flag specifying whether query should be forced to expand to all searchable fields */
|
||||
private Boolean useAllFields;
|
||||
|
||||
/** Further search settings needed by the ES specific query string parser only. */
|
||||
private Settings settings = new Settings();
|
||||
@ -166,6 +169,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
minimumShouldMatch = in.readOptionalString();
|
||||
if (in.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
|
||||
settings.quoteFieldSuffix(in.readOptionalString());
|
||||
useAllFields = in.readOptionalBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,6 +195,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
out.writeOptionalString(minimumShouldMatch);
|
||||
if (out.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
|
||||
out.writeOptionalString(settings.quoteFieldSuffix());
|
||||
out.writeOptionalBoolean(useAllFields);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,6 +245,15 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
return this.analyzer;
|
||||
}
|
||||
|
||||
public Boolean useAllFields() {
|
||||
return useAllFields;
|
||||
}
|
||||
|
||||
public SimpleQueryStringBuilder useAllFields(Boolean useAllFields) {
|
||||
this.useAllFields = useAllFields;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the default operator for the query. Defaults to "OR" if no
|
||||
* operator is specified.
|
||||
@ -341,17 +355,37 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
// field names in builder can have wildcards etc, need to resolve them here
|
||||
Map<String, Float> resolvedFieldsAndWeights = new TreeMap<>();
|
||||
// Use the default field if no fields specified
|
||||
if (fieldsAndWeights.isEmpty()) {
|
||||
resolvedFieldsAndWeights.put(resolveIndexName(context.defaultField(), context), AbstractQueryBuilder.DEFAULT_BOOST);
|
||||
|
||||
if ((useAllFields != null && useAllFields) && (fieldsAndWeights.size() != 0)) {
|
||||
throw addValidationError("cannot use [all_fields] parameter in conjunction with [fields]", null);
|
||||
}
|
||||
|
||||
// If explicitly required to use all fields, use all fields, OR:
|
||||
// Automatically determine the fields (to replace the _all field) if all of the following are true:
|
||||
// - The _all field is disabled,
|
||||
// - and the default_field has not been changed in the settings
|
||||
// - and no fields are specified in the request
|
||||
Settings newSettings = new Settings(settings);
|
||||
if ((this.useAllFields != null && this.useAllFields) ||
|
||||
(context.getMapperService().allEnabled() == false &&
|
||||
"_all".equals(context.defaultField()) &&
|
||||
this.fieldsAndWeights.isEmpty())) {
|
||||
resolvedFieldsAndWeights = QueryStringQueryBuilder.allQueryableDefaultFields(context);
|
||||
// Need to use lenient mode when using "all-mode" so exceptions aren't thrown due to mismatched types
|
||||
newSettings.lenient(true);
|
||||
} else {
|
||||
for (Map.Entry<String, Float> fieldEntry : fieldsAndWeights.entrySet()) {
|
||||
if (Regex.isSimpleMatchPattern(fieldEntry.getKey())) {
|
||||
for (String fieldName : context.getMapperService().simpleMatchToIndexNames(fieldEntry.getKey())) {
|
||||
resolvedFieldsAndWeights.put(fieldName, fieldEntry.getValue());
|
||||
// Use the default field if no fields specified
|
||||
if (fieldsAndWeights.isEmpty()) {
|
||||
resolvedFieldsAndWeights.put(resolveIndexName(context.defaultField(), context), AbstractQueryBuilder.DEFAULT_BOOST);
|
||||
} else {
|
||||
for (Map.Entry<String, Float> fieldEntry : fieldsAndWeights.entrySet()) {
|
||||
if (Regex.isSimpleMatchPattern(fieldEntry.getKey())) {
|
||||
for (String fieldName : context.getMapperService().simpleMatchToIndexNames(fieldEntry.getKey())) {
|
||||
resolvedFieldsAndWeights.put(fieldName, fieldEntry.getValue());
|
||||
}
|
||||
} else {
|
||||
resolvedFieldsAndWeights.put(resolveIndexName(fieldEntry.getKey(), context), fieldEntry.getValue());
|
||||
}
|
||||
} else {
|
||||
resolvedFieldsAndWeights.put(resolveIndexName(fieldEntry.getKey(), context), fieldEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,7 +403,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
|
||||
}
|
||||
|
||||
SimpleQueryParser sqp = new SimpleQueryParser(luceneAnalyzer, resolvedFieldsAndWeights, flags, settings, context);
|
||||
SimpleQueryParser sqp = new SimpleQueryParser(luceneAnalyzer, resolvedFieldsAndWeights, flags, newSettings, context);
|
||||
sqp.setDefaultOperator(defaultOperator.toBooleanClauseOccur());
|
||||
|
||||
Query query = sqp.parse(queryText);
|
||||
@ -419,6 +453,9 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
if (minimumShouldMatch != null) {
|
||||
builder.field(MINIMUM_SHOULD_MATCH_FIELD.getPreferredName(), minimumShouldMatch);
|
||||
}
|
||||
if (useAllFields != null) {
|
||||
builder.field(ALL_FIELDS_FIELD.getPreferredName(), useAllFields);
|
||||
}
|
||||
|
||||
printBoostAndQueryName(builder);
|
||||
builder.endObject();
|
||||
@ -439,6 +476,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
boolean lenient = SimpleQueryStringBuilder.DEFAULT_LENIENT;
|
||||
boolean analyzeWildcard = SimpleQueryStringBuilder.DEFAULT_ANALYZE_WILDCARD;
|
||||
String quoteFieldSuffix = null;
|
||||
Boolean useAllFields = null;
|
||||
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
@ -502,6 +540,8 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
minimumShouldMatch = parser.textOrNull();
|
||||
} else if (parseContext.getParseFieldMatcher().match(currentFieldName, QUOTE_FIELD_SUFFIX_FIELD)) {
|
||||
quoteFieldSuffix = parser.textOrNull();
|
||||
} else if (parseContext.getParseFieldMatcher().match(currentFieldName, ALL_FIELDS_FIELD)) {
|
||||
useAllFields = parser.booleanValue();
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "[" + SimpleQueryStringBuilder.NAME +
|
||||
"] unsupported field [" + parser.currentName() + "]");
|
||||
@ -517,10 +557,16 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
throw new ParsingException(parser.getTokenLocation(), "[" + SimpleQueryStringBuilder.NAME + "] query text missing");
|
||||
}
|
||||
|
||||
if ((useAllFields != null && useAllFields) && (fieldsAndWeights.size() != 0)) {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"cannot use [all_fields] parameter in conjunction with [fields]");
|
||||
}
|
||||
|
||||
SimpleQueryStringBuilder qb = new SimpleQueryStringBuilder(queryBody);
|
||||
qb.boost(boost).fields(fieldsAndWeights).analyzer(analyzerName).queryName(queryName).minimumShouldMatch(minimumShouldMatch);
|
||||
qb.flags(flags).defaultOperator(defaultOperator);
|
||||
qb.lenient(lenient).analyzeWildcard(analyzeWildcard).boost(boost).quoteFieldSuffix(quoteFieldSuffix);
|
||||
qb.useAllFields(useAllFields);
|
||||
return Optional.of(qb);
|
||||
}
|
||||
|
||||
@ -531,7 +577,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(fieldsAndWeights, analyzer, defaultOperator, queryText, minimumShouldMatch, settings, flags);
|
||||
return Objects.hash(fieldsAndWeights, analyzer, defaultOperator, queryText, minimumShouldMatch, settings, flags, useAllFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -539,7 +585,8 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
|
||||
return Objects.equals(fieldsAndWeights, other.fieldsAndWeights) && Objects.equals(analyzer, other.analyzer)
|
||||
&& Objects.equals(defaultOperator, other.defaultOperator) && Objects.equals(queryText, other.queryText)
|
||||
&& Objects.equals(minimumShouldMatch, other.minimumShouldMatch)
|
||||
&& Objects.equals(settings, other.settings) && (flags == other.flags);
|
||||
&& Objects.equals(settings, other.settings)
|
||||
&& (flags == other.flags)
|
||||
&& (useAllFields == other.useAllFields);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,8 @@ import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||
|
||||
@ -42,6 +44,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
@ -252,7 +255,12 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
|
||||
Map.Entry<String, Float> field = queryBuilder.fields().entrySet().iterator().next();
|
||||
assertTermOrBoostQuery(query, field.getKey(), queryBuilder.value(), field.getValue());
|
||||
} else if (queryBuilder.fields().size() == 0) {
|
||||
assertTermQuery(query, MetaData.ALL, queryBuilder.value());
|
||||
MapperService ms = context.mapperService();
|
||||
if (ms.allEnabled()) {
|
||||
assertTermQuery(query, MetaData.ALL, queryBuilder.value());
|
||||
} else {
|
||||
assertThat(query.getClass(), equalTo(MatchNoDocsQuery.class));
|
||||
}
|
||||
} else {
|
||||
fail("Encountered lucene query type we do not have a validation implementation for in our "
|
||||
+ SimpleQueryStringBuilderTests.class.getSimpleName());
|
||||
@ -398,4 +406,19 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
|
||||
expected = new FuzzyQuery(new Term(STRING_FIELD_NAME, "abc"), 1);
|
||||
assertEquals(expected, query);
|
||||
}
|
||||
|
||||
public void testAllFieldsWithFields() throws IOException {
|
||||
String json =
|
||||
"{\n" +
|
||||
" \"simple_query_string\" : {\n" +
|
||||
" \"query\" : \"this that thus\",\n" +
|
||||
" \"fields\" : [\"foo\"],\n" +
|
||||
" \"all_fields\" : true\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
ParsingException e = expectThrows(ParsingException.class, () -> parseQuery(json));
|
||||
assertThat(e.getMessage(),
|
||||
containsString("cannot use [all_fields] parameter in conjunction with [fields]"));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.search.query;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
@ -27,6 +28,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.query.Operator;
|
||||
import org.elasticsearch.index.query.QueryStringQueryBuilder;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
@ -201,33 +203,36 @@ public class QueryStringIT extends ESIntegTestCase {
|
||||
assertHits(resp.getHits(), "2", "3");
|
||||
assertHitCount(resp, 2L);
|
||||
|
||||
// Will be fixed once https://github.com/elastic/elasticsearch/pull/20965 is in
|
||||
// resp = client().prepareSearch("test")
|
||||
// .setQuery(queryStringQuery("Foo Bar").splitOnWhitespcae(false))
|
||||
// .get();
|
||||
// assertHits(resp.getHits(), "1", "2", "3");
|
||||
// assertHitCount(resp, 3L);
|
||||
resp = client().prepareSearch("test")
|
||||
.setQuery(queryStringQuery("Foo Bar").splitOnWhitespace(false))
|
||||
.get();
|
||||
assertHits(resp.getHits(), "1", "2", "3");
|
||||
assertHitCount(resp, 3L);
|
||||
}
|
||||
|
||||
public void testExplicitAllFieldsRequested() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index-with-all.json");
|
||||
prepareCreate("test2").setSource(indexBody).get();
|
||||
ensureGreen("test2");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo",
|
||||
"f_date", "2015/09/02",
|
||||
"f_float", "1.7",
|
||||
"f_ip", "127.0.0.1"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f1", "bar",
|
||||
"f_date", "2015/09/01",
|
||||
"f_float", "1.8",
|
||||
"f_ip", "127.0.0.2"));
|
||||
reqs.add(client().prepareIndex("test2", "doc", "1").setSource("f1", "foo", "f2", "eggplant"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(
|
||||
queryStringQuery("127.0.0.2 \"2015/09/02\"")
|
||||
.field("f_ip") // Usually this would mean we wouldn't search "all" fields
|
||||
.useAllFields(true)) // ... unless explicitly requested
|
||||
.get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
SearchResponse resp = client().prepareSearch("test2").setQuery(
|
||||
queryStringQuery("foo eggplent").defaultOperator(Operator.AND)).get();
|
||||
assertHitCount(resp, 0L);
|
||||
|
||||
resp = client().prepareSearch("test2").setQuery(
|
||||
queryStringQuery("foo eggplent").defaultOperator(Operator.AND).useAllFields(true)).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
assertHitCount(resp, 1L);
|
||||
|
||||
Exception e = expectThrows(Exception.class, () ->
|
||||
client().prepareSearch("test2").setQuery(
|
||||
queryStringQuery("blah").field("f1").useAllFields(true)).get());
|
||||
assertThat(ExceptionsHelper.detailedMessage(e),
|
||||
containsString("cannot use [all_fields] parameter in conjunction with [default_field] or [fields]"));
|
||||
}
|
||||
|
||||
@LuceneTestCase.AwaitsFix(bugUrl="currently can't perform phrase queries on fields that don't support positions")
|
||||
|
@ -19,23 +19,33 @@
|
||||
|
||||
package org.elasticsearch.search.query;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.Operator;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.SimpleQueryStringFlag;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.simpleQueryStringQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.test.StreamsUtils.copyToStringFromClasspath;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFirstHit;
|
||||
@ -43,6 +53,8 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitC
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
@ -352,4 +364,212 @@ public class SimpleQueryStringIT extends ESIntegTestCase {
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, 0L);
|
||||
}
|
||||
|
||||
public void testBasicAllQuery() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo bar baz"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f2", "Bar"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "3").setSource("f3", "foo bar baz"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foo")).get();
|
||||
assertHitCount(resp, 2L);
|
||||
assertHits(resp.getHits(), "1", "3");
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("bar")).get();
|
||||
assertHitCount(resp, 2L);
|
||||
assertHits(resp.getHits(), "1", "3");
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("Bar")).get();
|
||||
assertHitCount(resp, 3L);
|
||||
assertHits(resp.getHits(), "1", "2", "3");
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foa")).get();
|
||||
assertHitCount(resp, 1L);
|
||||
assertHits(resp.getHits(), "3");
|
||||
}
|
||||
|
||||
public void testWithDate() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo", "f_date", "2015/09/02"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f1", "bar", "f_date", "2015/09/01"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foo bar")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("\"2015/09/02\"")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
assertHitCount(resp, 1L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("bar \"2015/09/02\"")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("\"2015/09/02\" \"2015/09/01\"")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
}
|
||||
|
||||
public void testWithLotsOfTypes() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo",
|
||||
"f_date", "2015/09/02",
|
||||
"f_float", "1.7",
|
||||
"f_ip", "127.0.0.1"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f1", "bar",
|
||||
"f_date", "2015/09/01",
|
||||
"f_float", "1.8",
|
||||
"f_ip", "127.0.0.2"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foo bar")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("\"2015/09/02\"")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
assertHitCount(resp, 1L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("127.0.0.2 \"2015/09/02\"")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("127.0.0.1 1.8")).get();
|
||||
assertHits(resp.getHits(), "1", "2");
|
||||
assertHitCount(resp, 2L);
|
||||
}
|
||||
|
||||
public void testDocWithAllTypes() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
String docBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-example-document.json");
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource(docBody));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foo")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("Bar")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("Baz")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("sbaz")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("19")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
// nested doesn't match because it's hidden
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("1476383971")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
// bool doesn't match
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("7")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("23")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("1293")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("42")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("1.7")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("1.5")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("12.23")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("127.0.0.1")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
// binary doesn't match
|
||||
// suggest doesn't match
|
||||
// geo_point doesn't match
|
||||
// geo_shape doesn't match
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(
|
||||
simpleQueryStringQuery("foo Bar 19 127.0.0.1").defaultOperator(Operator.AND)).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
}
|
||||
|
||||
public void testKeywordWithWhitespace() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f2", "Foo Bar"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f1", "bar"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "3").setSource("f1", "foo bar"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("foo")).get();
|
||||
assertHits(resp.getHits(), "3");
|
||||
assertHitCount(resp, 1L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("bar")).get();
|
||||
assertHits(resp.getHits(), "2", "3");
|
||||
assertHitCount(resp, 2L);
|
||||
}
|
||||
|
||||
public void testExplicitAllFieldsRequested() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index-with-all.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo", "f2", "eggplant"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(
|
||||
simpleQueryStringQuery("foo eggplent").defaultOperator(Operator.AND)).get();
|
||||
assertHitCount(resp, 0L);
|
||||
|
||||
resp = client().prepareSearch("test").setQuery(
|
||||
simpleQueryStringQuery("foo eggplent").defaultOperator(Operator.AND).useAllFields(true)).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
assertHitCount(resp, 1L);
|
||||
|
||||
Exception e = expectThrows(Exception.class, () ->
|
||||
client().prepareSearch("test").setQuery(
|
||||
simpleQueryStringQuery("blah").field("f1").useAllFields(true)).get());
|
||||
assertThat(ExceptionsHelper.detailedMessage(e),
|
||||
containsString("cannot use [all_fields] parameter in conjunction with [fields]"));
|
||||
}
|
||||
|
||||
@LuceneTestCase.AwaitsFix(bugUrl="currently can't perform phrase queries on fields that don't support positions")
|
||||
public void testPhraseQueryOnFieldWithNoPositions() throws Exception {
|
||||
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
|
||||
prepareCreate("test").setSource(indexBody).get();
|
||||
ensureGreen("test");
|
||||
|
||||
List<IndexRequestBuilder> reqs = new ArrayList<>();
|
||||
reqs.add(client().prepareIndex("test", "doc", "1").setSource("f1", "foo bar", "f4", "eggplant parmesan"));
|
||||
reqs.add(client().prepareIndex("test", "doc", "2").setSource("f1", "foo bar", "f4", "chicken parmesan"));
|
||||
indexRandom(true, false, reqs);
|
||||
|
||||
SearchResponse resp = client().prepareSearch("test").setQuery(simpleQueryStringQuery("\"eggplant parmesan\"")).get();
|
||||
assertHits(resp.getHits(), "1");
|
||||
assertHitCount(resp, 1L);
|
||||
}
|
||||
|
||||
private void assertHits(SearchHits hits, String... ids) {
|
||||
assertThat(hits.totalHits(), equalTo((long) ids.length));
|
||||
Set<String> hitIds = new HashSet<>();
|
||||
for (SearchHit hit : hits.getHits()) {
|
||||
hitIds.add(hit.id());
|
||||
}
|
||||
assertThat(hitIds, containsInAnyOrder(ids));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
{
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_shards": 1,
|
||||
"number_of_replicas": 0,
|
||||
"analysis": {
|
||||
"analyzer": {
|
||||
"my_ngrams": {
|
||||
"type": "custom",
|
||||
"tokenizer": "standard",
|
||||
"filter": ["my_ngrams"]
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"my_ngrams": {
|
||||
"type": "ngram",
|
||||
"min_gram": 2,
|
||||
"max_gram": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mappings": {
|
||||
"doc": {
|
||||
"_all": {
|
||||
"enabled": true
|
||||
},
|
||||
"properties": {
|
||||
"f1": {"type": "text"},
|
||||
"f2": {"type": "text", "analyzer": "my_ngrams"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -61,6 +61,10 @@ based just on the prefix of a term. Defaults to `false`.
|
||||
the query string. This allows to use a field that has a different analysis chain
|
||||
for exact matching. Look <<mixing-exact-search-with-stemming,here>> for a
|
||||
comprehensive example.
|
||||
|
||||
|`all_fields` | Perform the query on all fields detected in the mapping that can
|
||||
be queried. Will be used by default when the `_all` field is disabled and no
|
||||
`default_field` is specified index settings, and no `fields` are specified.
|
||||
|=======================================================================
|
||||
|
||||
[float]
|
||||
@ -85,8 +89,10 @@ When not explicitly specifying the field to search on in the query
|
||||
string syntax, the `index.query.default_field` will be used to derive
|
||||
which field to search on. It defaults to `_all` field.
|
||||
|
||||
So, if `_all` field is disabled, it might make sense to change it to set
|
||||
a different default field.
|
||||
If the `_all` field is disabled and no `fields` are specified in the request`,
|
||||
the `simple_query_string` query will automatically attempt to determine the
|
||||
existing fields in the index's mapping that are queryable, and perform the
|
||||
search on those fields.
|
||||
|
||||
[float]
|
||||
==== Multi Field
|
||||
|
Loading…
x
Reference in New Issue
Block a user