Minor improvements to indices filter and query & updated docs
Slightly simplified indices filter and query parsers code Trimmed down tests where possible
This commit is contained in:
parent
fa80ca97b2
commit
0aaa39d00a
|
@ -71,6 +71,8 @@ include::filters/has-parent-filter.asciidoc[]
|
|||
|
||||
include::filters/ids-filter.asciidoc[]
|
||||
|
||||
include::filters/indices-filter.asciidoc[]
|
||||
|
||||
include::filters/limit-filter.asciidoc[]
|
||||
|
||||
include::filters/match-all-filter.asciidoc[]
|
||||
|
|
|
@ -26,13 +26,13 @@ You can use the `index` field to provide a single index.
|
|||
`no_match_filter` can also have "string" value of `none` (to match no
|
||||
documents), and `all` (to match all). Defaults to `all`.
|
||||
|
||||
`filter` is mandatory. You must provide the indices.
|
||||
It is forbidden to omit or to give `indices` or `index` multiple times,
|
||||
or to give both.
|
||||
`filter` is mandatory, as well as `indices` (or `index`).
|
||||
|
||||
Please note that the fields order is important: If the indices are
|
||||
provided before `filter` or `no_match_filter`, the filter parsing is
|
||||
skipped altogether.
|
||||
For instance, this feature is useful to prevent a query that runs
|
||||
against multiple indices to fail because of a missing type.
|
||||
See `has_child`, `has_parent`, `top_children` and `nested`.
|
||||
coming[0.90.8]
|
||||
[TIP]
|
||||
===================================================================
|
||||
The fields order is important: if the `indices` are provided before `filter`
|
||||
or `no_match_filter`, the related filters get parsed only against the indices
|
||||
that they are going to be executed on. This is useful to avoid parsing filters
|
||||
when it is not necessary and prevent potential mapping errors.
|
||||
===================================================================
|
|
@ -26,13 +26,13 @@ You can use the `index` field to provide a single index.
|
|||
`no_match_query` can also have "string" value of `none` (to match no
|
||||
documents), and `all` (to match all). Defaults to `all`.
|
||||
|
||||
`query` is mandatory. You must provide the indices.
|
||||
It is forbidden to omit or to give `indices` or `index` multiple times,
|
||||
or to give both.
|
||||
`query` is mandatory, as well as `indices` (or `index`).
|
||||
|
||||
Please note that the fields order is important: If the indices are
|
||||
provided before `query` or `no_match_query`, the query parsing is
|
||||
skipped altogether.
|
||||
For instance, this feature is useful to prevent a query that runs
|
||||
against multiple indices to fail because of a missing type.
|
||||
See `has_child`, `has_parent`, `top_children` and `nested`.
|
||||
coming[0.90.8]
|
||||
[TIP]
|
||||
===================================================================
|
||||
The fields order is important: if the `indices` are provided before `query`
|
||||
or `no_match_query`, the related queries get parsed only against the indices
|
||||
that they are going to be executed on. This is useful to avoid parsing queries
|
||||
when it is not necessary and prevent potential mapping errors.
|
||||
===================================================================
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.index.query;
|
|||
import org.apache.lucene.search.Filter;
|
||||
import org.elasticsearch.action.support.IgnoreIndices;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
|
@ -31,7 +30,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
|
@ -59,10 +57,9 @@ public class IndicesFilterParser implements FilterParser {
|
|||
|
||||
Filter filter = null;
|
||||
Filter noMatchFilter = Queries.MATCH_ALL_FILTER;
|
||||
Filter chosenFilter = null;
|
||||
boolean filterFound = false;
|
||||
boolean indicesFound = false;
|
||||
boolean matchesConcreteIndices = false;
|
||||
boolean currentIndexMatchesIndices = false;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
|
@ -72,29 +69,16 @@ public class IndicesFilterParser implements FilterParser {
|
|||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("filter".equals(currentFieldName)) {
|
||||
filterFound = true;
|
||||
if (indicesFound) {
|
||||
// Because we know the indices, we can either skip, or parse and use the query
|
||||
if (matchesConcreteIndices) {
|
||||
filter = parseContext.parseInnerFilter();
|
||||
chosenFilter = filter;
|
||||
} else {
|
||||
parseContext.parser().skipChildren(); // skip the filter object without parsing it into a Filter
|
||||
}
|
||||
//TODO We are able to decide whether to parse the filter or not only if indices in the query appears first
|
||||
if (indicesFound && !currentIndexMatchesIndices) {
|
||||
parseContext.parser().skipChildren(); // skip the filter object without parsing it
|
||||
} else {
|
||||
// We do not know the indices, we must parse the query
|
||||
filter = parseContext.parseInnerFilter();
|
||||
}
|
||||
} else if ("no_match_filter".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
// Because we know the indices, we can either skip, or parse and use the query
|
||||
if (!matchesConcreteIndices) {
|
||||
noMatchFilter = parseContext.parseInnerFilter();
|
||||
chosenFilter = noMatchFilter;
|
||||
} else {
|
||||
parseContext.parser().skipChildren(); // skip the filter object without parsing it into a Filter
|
||||
}
|
||||
if (indicesFound && currentIndexMatchesIndices) {
|
||||
parseContext.parser().skipChildren(); // skip the filter object without parsing it
|
||||
} else {
|
||||
// We do not know the indices, we must parse the query
|
||||
noMatchFilter = parseContext.parseInnerFilter();
|
||||
}
|
||||
} else {
|
||||
|
@ -103,28 +87,28 @@ public class IndicesFilterParser implements FilterParser {
|
|||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("indices".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices already specified");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices or index already specified");
|
||||
}
|
||||
indicesFound = true;
|
||||
Collection<String> indices = new ArrayList<String>();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||
String value = parser.textOrNull();
|
||||
if (value == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] no value specified for 'indices' entry");
|
||||
}
|
||||
indices.add(value);
|
||||
}
|
||||
matchesConcreteIndices = matchesIndices(parseContext, getConcreteIndices(indices));
|
||||
currentIndexMatchesIndices = matchesIndices(parseContext.index().name(), indices.toArray(new String[indices.size()]));
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] filter does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("index".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices already specified");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices or index already specified");
|
||||
}
|
||||
indicesFound = true;
|
||||
matchesConcreteIndices = matchesIndices(parseContext, getConcreteIndices(Arrays.asList(parser.text())));
|
||||
currentIndexMatchesIndices = matchesIndices(parseContext.index().name(), parser.text());
|
||||
} else if ("no_match_filter".equals(currentFieldName)) {
|
||||
String type = parser.text();
|
||||
if ("all".equals(type)) {
|
||||
|
@ -132,11 +116,6 @@ public class IndicesFilterParser implements FilterParser {
|
|||
} else if ("none".equals(type)) {
|
||||
noMatchFilter = Queries.MATCH_NO_FILTER;
|
||||
}
|
||||
if (indicesFound) {
|
||||
if (!matchesConcreteIndices) {
|
||||
chosenFilter = noMatchFilter;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] filter does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
@ -146,34 +125,19 @@ public class IndicesFilterParser implements FilterParser {
|
|||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'filter' element");
|
||||
}
|
||||
if (!indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' element");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' or 'index' element");
|
||||
}
|
||||
|
||||
if (chosenFilter == null) {
|
||||
// Indices were not provided before we encountered the queries, which we hence parsed
|
||||
// We must now make a choice
|
||||
if (matchesConcreteIndices) {
|
||||
chosenFilter = filter;
|
||||
} else {
|
||||
chosenFilter = noMatchFilter;
|
||||
}
|
||||
if (currentIndexMatchesIndices) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
return chosenFilter;
|
||||
return noMatchFilter;
|
||||
}
|
||||
|
||||
protected String[] getConcreteIndices(Collection<String> indices) {
|
||||
String[] concreteIndices = indices.toArray(new String[indices.size()]);
|
||||
if (clusterService != null) {
|
||||
MetaData metaData = clusterService.state().metaData();
|
||||
concreteIndices = metaData.concreteIndices(indices.toArray(new String[indices.size()]), IgnoreIndices.MISSING, true);
|
||||
}
|
||||
return concreteIndices;
|
||||
}
|
||||
|
||||
protected boolean matchesIndices(QueryParseContext parseContext, String[] concreteIndices) {
|
||||
protected boolean matchesIndices(String currentIndex, String... indices) {
|
||||
String[] concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
|
||||
for (String index : concreteIndices) {
|
||||
if (Regex.simpleMatch(index, parseContext.index().name())) {
|
||||
if (Regex.simpleMatch(index, currentIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.index.query;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.action.support.IgnoreIndices;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
|
@ -31,7 +30,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
|
@ -59,10 +57,9 @@ public class IndicesQueryParser implements QueryParser {
|
|||
|
||||
Query query = null;
|
||||
Query noMatchQuery = Queries.newMatchAllQuery();
|
||||
Query chosenQuery = null;
|
||||
boolean queryFound = false;
|
||||
boolean indicesFound = false;
|
||||
boolean matchesConcreteIndices = false;
|
||||
boolean currentIndexMatchesIndices = false;
|
||||
String queryName = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
|
@ -72,30 +69,17 @@ public class IndicesQueryParser implements QueryParser {
|
|||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("query".equals(currentFieldName)) {
|
||||
//TODO We are able to decide whether to parse the query or not only if indices in the query appears first
|
||||
queryFound = true;
|
||||
if (indicesFound) {
|
||||
// Because we know the indices, we can either skip, or parse and use the query
|
||||
if (matchesConcreteIndices) {
|
||||
query = parseContext.parseInnerQuery();
|
||||
chosenQuery = query;
|
||||
} else {
|
||||
parseContext.parser().skipChildren(); // skip the query object without parsing it into a Query
|
||||
}
|
||||
if (indicesFound && !currentIndexMatchesIndices) {
|
||||
parseContext.parser().skipChildren(); // skip the query object without parsing it
|
||||
} else {
|
||||
// We do not know the indices, we must parse the query
|
||||
query = parseContext.parseInnerQuery();
|
||||
}
|
||||
} else if ("no_match_query".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
// Because we know the indices, we can either skip, or parse and use the query
|
||||
if (!matchesConcreteIndices) {
|
||||
noMatchQuery = parseContext.parseInnerQuery();
|
||||
chosenQuery = noMatchQuery;
|
||||
} else {
|
||||
parseContext.parser().skipChildren(); // skip the query object without parsing it into a Query
|
||||
}
|
||||
if (indicesFound && currentIndexMatchesIndices) {
|
||||
parseContext.parser().skipChildren(); // skip the query object without parsing it
|
||||
} else {
|
||||
// We do not know the indices, we must parse the query
|
||||
noMatchQuery = parseContext.parseInnerQuery();
|
||||
}
|
||||
} else {
|
||||
|
@ -104,28 +88,28 @@ public class IndicesQueryParser implements QueryParser {
|
|||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("indices".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices already specified");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices or index already specified");
|
||||
}
|
||||
indicesFound = true;
|
||||
Collection<String> indices = new ArrayList<String>();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||
String value = parser.textOrNull();
|
||||
if (value == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] no value specified for 'indices' entry");
|
||||
}
|
||||
indices.add(value);
|
||||
}
|
||||
matchesConcreteIndices = matchesIndices(parseContext, getConcreteIndices(indices));
|
||||
currentIndexMatchesIndices = matchesIndices(parseContext.index().name(), indices.toArray(new String[indices.size()]));
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("index".equals(currentFieldName)) {
|
||||
if (indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices already specified");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] indices or index already specified");
|
||||
}
|
||||
indicesFound = true;
|
||||
matchesConcreteIndices = matchesIndices(parseContext, getConcreteIndices(Arrays.asList(parser.text())));
|
||||
currentIndexMatchesIndices = matchesIndices(parseContext.index().name(), parser.text());
|
||||
} else if ("no_match_query".equals(currentFieldName)) {
|
||||
String type = parser.text();
|
||||
if ("all".equals(type)) {
|
||||
|
@ -133,11 +117,6 @@ public class IndicesQueryParser implements QueryParser {
|
|||
} else if ("none".equals(type)) {
|
||||
noMatchQuery = Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
if (indicesFound) {
|
||||
if (!matchesConcreteIndices) {
|
||||
chosenQuery = noMatchQuery;
|
||||
}
|
||||
}
|
||||
} else if ("_name".equals(currentFieldName)) {
|
||||
queryName = parser.text();
|
||||
} else {
|
||||
|
@ -149,38 +128,25 @@ public class IndicesQueryParser implements QueryParser {
|
|||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'query' element");
|
||||
}
|
||||
if (!indicesFound) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' element");
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' or 'index' element");
|
||||
}
|
||||
|
||||
if (chosenQuery == null) {
|
||||
// Indices were not provided before we encountered the queries, which we hence parsed
|
||||
// We must now make a choice
|
||||
if (matchesConcreteIndices) {
|
||||
chosenQuery = query;
|
||||
} else {
|
||||
chosenQuery = noMatchQuery;
|
||||
}
|
||||
Query chosenQuery;
|
||||
if (currentIndexMatchesIndices) {
|
||||
chosenQuery = query;
|
||||
} else {
|
||||
chosenQuery = noMatchQuery;
|
||||
}
|
||||
|
||||
if (queryName != null && chosenQuery != null) {
|
||||
if (queryName != null) {
|
||||
parseContext.addNamedQuery(queryName, chosenQuery);
|
||||
}
|
||||
|
||||
return chosenQuery;
|
||||
}
|
||||
|
||||
protected String[] getConcreteIndices(Collection<String> indices) {
|
||||
String[] concreteIndices = indices.toArray(new String[indices.size()]);
|
||||
if (clusterService != null) {
|
||||
MetaData metaData = clusterService.state().metaData();
|
||||
concreteIndices = metaData.concreteIndices(indices.toArray(new String[indices.size()]), IgnoreIndices.MISSING, true);
|
||||
}
|
||||
return concreteIndices;
|
||||
}
|
||||
|
||||
protected boolean matchesIndices(QueryParseContext parseContext, String[] concreteIndices) {
|
||||
protected boolean matchesIndices(String currentIndex, String... indices) {
|
||||
String[] concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
|
||||
for (String index : concreteIndices) {
|
||||
if (Regex.simpleMatch(index, parseContext.index().name())) {
|
||||
if (Regex.simpleMatch(index, currentIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.elasticsearch.action.index.IndexRequestBuilder;
|
|||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
|
@ -1893,35 +1894,39 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
|
|||
|
||||
@Test
|
||||
public void testIndicesQuery() throws Exception {
|
||||
createIndex("index1", "index2");
|
||||
createIndex("index1", "index2", "index3");
|
||||
ensureGreen();
|
||||
|
||||
client().prepareIndex("index1", "type1").setId("1").setSource("text", "value").get();
|
||||
client().prepareIndex("index2", "type2").setId("2").setSource("text", "value").get();
|
||||
client().prepareIndex("index1", "type1").setId("1").setSource("text", "value1").get();
|
||||
client().prepareIndex("index2", "type2").setId("2").setSource("text", "value2").get();
|
||||
client().prepareIndex("index3", "type3").setId("3").setSource("text", "value3").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value"), "index1")
|
||||
.noMatchQuery(matchQuery("text", "value"))).get();
|
||||
SearchResponse response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value1"), "index1")
|
||||
.noMatchQuery(matchQuery("text", "value2"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value"), "index1")).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
//default no match query is match_all
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value1"), "index1")).get();
|
||||
assertHitCount(response, 3l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(2).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value"), "index1")
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value1"), "index1")
|
||||
.noMatchQuery("all")).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertHitCount(response, 3l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(2).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value"), "index1")
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setQuery(indicesQuery(matchQuery("text", "value1"), "index1")
|
||||
.noMatchQuery("none")).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
|
@ -1929,137 +1934,108 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
|
|||
|
||||
@Test
|
||||
public void testIndicesFilter() throws Exception {
|
||||
createIndex("index1", "index2");
|
||||
createIndex("index1", "index2", "index3");
|
||||
ensureGreen();
|
||||
|
||||
client().prepareIndex("index1", "type1").setId("1").setSource("text", "value").get();
|
||||
client().prepareIndex("index2", "type2").setId("2").setSource("text", "value").get();
|
||||
client().prepareIndex("index1", "type1").setId("1").setSource("text", "value1").get();
|
||||
client().prepareIndex("index2", "type2").setId("2").setSource("text", "value2").get();
|
||||
client().prepareIndex("index3", "type3").setId("3").setSource("text", "value3").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse response = client().prepareSearch("index1", "index2")
|
||||
.setFilter(indicesFilter(termFilter("text", "value"), "index1")
|
||||
.noMatchFilter(termFilter("text", "value"))).get();
|
||||
SearchResponse response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setFilter(indicesFilter(termFilter("text", "value1"), "index1")
|
||||
.noMatchFilter(termFilter("text", "value2"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setFilter(indicesFilter(termFilter("text", "value"), "index1")).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
//default no match filter is "all"
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setFilter(indicesFilter(termFilter("text", "value1"), "index1")).get();
|
||||
assertHitCount(response, 3l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(2).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setFilter(indicesFilter(termFilter("text", "value"), "index1")
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setFilter(indicesFilter(termFilter("text", "value1"), "index1")
|
||||
.noMatchFilter("all")).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertHitCount(response, 3l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
assertThat(response.getHits().getAt(2).getId(), either(equalTo("1")).or(equalTo("2")).or(equalTo("3")));
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setFilter(indicesFilter(termFilter("text", "value"), "index1")
|
||||
response = client().prepareSearch("index1", "index2", "index3")
|
||||
.setFilter(indicesFilter(termFilter("text", "value1"), "index1")
|
||||
.noMatchFilter("none")).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
}
|
||||
|
||||
@Test // https://github.com/elasticsearch/elasticsearch/issues/2416
|
||||
public void testIndicesQueryHideParsingExceptions() throws Exception {
|
||||
client().admin().indices().prepareCreate("simple")
|
||||
.addMapping("lone", jsonBuilder().startObject().startObject("lone").endObject().endObject())
|
||||
.get();
|
||||
public void testIndicesQuerySkipParsing() throws Exception {
|
||||
createIndex("simple");
|
||||
client().admin().indices().prepareCreate("related")
|
||||
.addMapping("parent", jsonBuilder().startObject().startObject("parent").endObject().endObject())
|
||||
.addMapping("child", jsonBuilder().startObject().startObject("child").startObject("_parent").field("type", "parent")
|
||||
.endObject().endObject().endObject())
|
||||
.get();
|
||||
ensureGreen();
|
||||
|
||||
client().prepareIndex("simple", "lone").setId("1").setSource("text", "value").get();
|
||||
client().prepareIndex("simple", "lone").setId("1").setSource("text", "value1").get();
|
||||
client().prepareIndex("related", "parent").setId("2").setSource("text", "parent").get();
|
||||
client().prepareIndex("related", "child").setId("3").setParent("2").setSource("text", "value").get();
|
||||
client().prepareIndex("related", "child").setId("3").setParent("2").setSource("text", "value2").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse response = client().prepareSearch("related")
|
||||
.setQuery(hasChildQuery("child", matchQuery("text", "value"))).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
|
||||
response = client().prepareSearch("simple")
|
||||
.setQuery(matchQuery("text", "value")).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
|
||||
//has_child fails if executed on "simple" index
|
||||
try {
|
||||
client().prepareSearch("simple")
|
||||
.setQuery(hasChildQuery("child", matchQuery("text", "value"))).get();
|
||||
fail("Should have failed with a SearchPhaseExecutionException because all shards failed with a nested QueryParsingException");
|
||||
// If no failure happens, the HasChildQuery may have changed behavior when provided with wrong types
|
||||
fail("Should have failed as has_child query can only be executed against parent-child types");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
// There is no easy way to ensure we got a QueryParsingException
|
||||
assertThat(e.shardFailures().length, greaterThan(0));
|
||||
for (ShardSearchFailure shardSearchFailure : e.shardFailures()) {
|
||||
assertThat(shardSearchFailure.reason(), containsString("No mapping for for type [child]"));
|
||||
}
|
||||
}
|
||||
|
||||
response = client().prepareSearch("related", "simple")
|
||||
.setQuery(indicesQuery(matchQuery("text", "parent"), "related")
|
||||
.noMatchQuery(matchQuery("text", "value"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
|
||||
response = client().prepareSearch("related", "simple")
|
||||
.setQuery(indicesQuery(hasChildQuery("child", matchQuery("text", "value")), "related")
|
||||
.noMatchQuery(matchQuery("text", "value"))).get();
|
||||
//has_child doesn't get parsed for "simple" index
|
||||
SearchResponse response = client().prepareSearch("related", "simple")
|
||||
.setQuery(indicesQuery(hasChildQuery("child", matchQuery("text", "value2")), "related")
|
||||
.noMatchQuery(matchQuery("text", "value1"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
}
|
||||
|
||||
@Test // https://github.com/elasticsearch/elasticsearch/issues/2416
|
||||
public void testIndicesFilterHideParsingExceptions() throws Exception {
|
||||
client().admin().indices().prepareCreate("simple")
|
||||
.addMapping("lone", jsonBuilder().startObject().startObject("lone").endObject().endObject())
|
||||
.get();
|
||||
public void testIndicesFilterSkipParsing() throws Exception {
|
||||
createIndex("simple");
|
||||
client().admin().indices().prepareCreate("related")
|
||||
.addMapping("parent", jsonBuilder().startObject().startObject("parent").endObject().endObject())
|
||||
.addMapping("child", jsonBuilder().startObject().startObject("child").startObject("_parent").field("type", "parent")
|
||||
.endObject().endObject().endObject())
|
||||
.get();
|
||||
ensureGreen();
|
||||
|
||||
client().prepareIndex("simple", "lone").setId("1").setSource("text", "value").get();
|
||||
client().prepareIndex("simple", "lone").setId("1").setSource("text", "value1").get();
|
||||
client().prepareIndex("related", "parent").setId("2").setSource("text", "parent").get();
|
||||
client().prepareIndex("related", "child").setId("3").setParent("2").setSource("text", "value").get();
|
||||
client().prepareIndex("related", "child").setId("3").setParent("2").setSource("text", "value2").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse response = client().prepareSearch("related")
|
||||
.setFilter(hasChildFilter("child", termFilter("text", "value"))).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
|
||||
response = client().prepareSearch("simple")
|
||||
.setFilter(termFilter("text", "value")).get();
|
||||
assertHitCount(response, 1l);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
|
||||
//has_child fails if executed on "simple" index
|
||||
try {
|
||||
client().prepareSearch("simple")
|
||||
.setFilter(hasChildFilter("child", termFilter("text", "value"))).get();
|
||||
fail("Should have failed with a SearchPhaseExecutionException because all shards failed with a nested QueryParsingException");
|
||||
// If no failure happens, the HasChildQuery may have changed behavior when provided with wrong types
|
||||
.setFilter(hasChildFilter("child", termFilter("text", "value1"))).get();
|
||||
fail("Should have failed as has_child query can only be executed against parent-child types");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
// There is no easy way to ensure we got a QueryParsingException
|
||||
assertThat(e.shardFailures().length, greaterThan(0));
|
||||
for (ShardSearchFailure shardSearchFailure : e.shardFailures()) {
|
||||
assertThat(shardSearchFailure.reason(), containsString("No mapping for for type [child]"));
|
||||
}
|
||||
}
|
||||
|
||||
response = client().prepareSearch("related", "simple")
|
||||
.setFilter(indicesFilter(termFilter("text", "parent"), "related")
|
||||
.noMatchFilter(termFilter("text", "value"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
|
||||
response = client().prepareSearch("related", "simple")
|
||||
.setFilter(indicesFilter(hasChildFilter("child", termFilter("text", "value")), "related")
|
||||
.noMatchFilter(termFilter("text", "value"))).get();
|
||||
SearchResponse response = client().prepareSearch("related", "simple")
|
||||
.setFilter(indicesFilter(hasChildFilter("child", termFilter("text", "value2")), "related")
|
||||
.noMatchFilter(termFilter("text", "value1"))).get();
|
||||
assertHitCount(response, 2l);
|
||||
assertThat(response.getHits().getAt(0).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
assertThat(response.getHits().getAt(1).getId(), either(equalTo("1")).or(equalTo("2")));
|
||||
|
|
Loading…
Reference in New Issue