Search enhancement: adds a special case for the “_index” field which allows queries to test the name of the index. Adding this capability means we can deprecate the specialist indices query.
IndexFieldMapper is changed to make the term query factories produce match_all or match_none queries based on tests on the index name. Closes #3316
This commit is contained in:
parent
d085088793
commit
f95981b977
|
@ -22,10 +22,13 @@ package org.elasticsearch.index.mapper.internal;
|
|||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.fielddata.FieldDataType;
|
||||
|
@ -34,9 +37,10 @@ import org.elasticsearch.index.mapper.Mapper;
|
|||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
||||
import org.elasticsearch.index.mapper.MergeResult;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
@ -135,6 +139,62 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
|||
return CONTENT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useTermQueryWithQueryString() {
|
||||
// As we spoof the presence of an indexed field we have to override
|
||||
// the default of returning false which otherwise leads MatchQuery
|
||||
// et al to run an analyzer over the query string and then try to
|
||||
// hit the search index. We need them to use our termQuery(..)
|
||||
// method which checks index names
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This termQuery impl looks at the context to determine the index that
|
||||
* is being queried and then returns a MATCH_ALL_QUERY or MATCH_NO_QUERY
|
||||
* if the value matches this index. This can be useful if aliases or
|
||||
* wildcards are used but the aim is to restrict the query to specific
|
||||
* indices
|
||||
*/
|
||||
@Override
|
||||
public Query termQuery(Object value, @Nullable QueryParseContext context) {
|
||||
if (context == null) {
|
||||
return super.termQuery(value, context);
|
||||
}
|
||||
if (isSameIndex(value, context.index().getName())) {
|
||||
return Queries.newMatchAllQuery();
|
||||
} else {
|
||||
return Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Query termsQuery(List values, QueryParseContext context) {
|
||||
if (context == null) {
|
||||
return super.termsQuery(values, context);
|
||||
}
|
||||
for (Object value : values) {
|
||||
if (isSameIndex(value, context.index().getName())) {
|
||||
// No need to OR these clauses - we can only logically be
|
||||
// running in the context of just one of these index names.
|
||||
return Queries.newMatchAllQuery();
|
||||
}
|
||||
}
|
||||
// None of the listed index names are this one
|
||||
return Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
|
||||
private boolean isSameIndex(Object value, String indexName) {
|
||||
if (value instanceof BytesRef) {
|
||||
BytesRef indexNameRef = new BytesRef(indexName);
|
||||
return (indexNameRef.bytesEquals((BytesRef) value));
|
||||
} else {
|
||||
return indexName.equals(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String value(Object value) {
|
||||
if (value == null) {
|
||||
|
|
|
@ -699,6 +699,58 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
|
|||
assertSearchHits(searchResponse, "1", "3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void term_indexQueryTestsIndexed() throws Exception {
|
||||
term_indexQueryTests("not_analyzed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void term_indexQueryTestsNotIndexed() throws Exception {
|
||||
term_indexQueryTests("no");
|
||||
}
|
||||
|
||||
private void term_indexQueryTests(String index) throws Exception {
|
||||
Settings indexSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
|
||||
String[] indexNames = { "test1", "test2" };
|
||||
for (String indexName : indexNames) {
|
||||
assertAcked(client()
|
||||
.admin()
|
||||
.indices()
|
||||
.prepareCreate(indexName)
|
||||
.setSettings(indexSettings)
|
||||
.addMapping(
|
||||
"type1",
|
||||
jsonBuilder().startObject().startObject("type1").startObject("_index").field("index", index).endObject()
|
||||
.endObject().endObject()));
|
||||
|
||||
indexRandom(true, client().prepareIndex(indexName, "type1", indexName + "1").setSource("field1", "value1"));
|
||||
|
||||
}
|
||||
for (String indexName : indexNames) {
|
||||
SearchResponse request = client().prepareSearch().setQuery(constantScoreQuery(termQuery("_index", indexName))).get();
|
||||
SearchResponse searchResponse = assertSearchResponse(request);
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertSearchHits(searchResponse, indexName + "1");
|
||||
}
|
||||
for (String indexName : indexNames) {
|
||||
SearchResponse request = client().prepareSearch().setQuery(constantScoreQuery(termsQuery("_index", indexName))).get();
|
||||
SearchResponse searchResponse = assertSearchResponse(request);
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertSearchHits(searchResponse, indexName + "1");
|
||||
}
|
||||
for (String indexName : indexNames) {
|
||||
SearchResponse request = client().prepareSearch().setQuery(constantScoreQuery(matchQuery("_index", indexName))).get();
|
||||
SearchResponse searchResponse = assertSearchResponse(request);
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertSearchHits(searchResponse, indexName + "1");
|
||||
}
|
||||
{
|
||||
SearchResponse request = client().prepareSearch().setQuery(constantScoreQuery(termsQuery("_index", indexNames))).get();
|
||||
SearchResponse searchResponse = assertSearchResponse(request);
|
||||
assertHitCount(searchResponse, indexNames.length);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitFilter() throws Exception {
|
||||
assertAcked(client().admin().indices().prepareCreate("test").setSettings(SETTING_NUMBER_OF_SHARDS, 1));
|
||||
|
|
Loading…
Reference in New Issue