Add support for aliases in queries on _index. (#46944)

Previously, queries on the _index field were not able to specify index aliases.
This was a regression in functionality compared to the 'indices' query that was
deprecated and removed in 6.0.

Now queries on _index can specify an alias, which is resolved to the concrete
index names when we check whether an index matches. To match a remote shard
target, the pattern needs to be of the form 'cluster:index' to match the
fully-qualified index name. Index aliases can be specified in the following query
types: term, terms, prefix, and wildcard.
This commit is contained in:
Julie Tibshirani 2019-09-23 13:21:37 -07:00 committed by GitHub
parent 08f28e642b
commit 9124c94a6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 392 additions and 139 deletions

View File

@ -0,0 +1,30 @@
[[breaking-changes-7.5]]
== Breaking changes in 7.5
++++
<titleabbrev>7.5</titleabbrev>
++++
This section discusses the changes that you need to be aware of when migrating
your application to Elasticsearch 7.5.
See also <<release-highlights>> and <<es-release-notes>>.
coming[7.5.0]
//NOTE: The notable-breaking-changes tagged regions are re-used in the
//Installation and Upgrade Guide
//tag::notable-breaking-changes[]
//end::notable-breaking-changes[]
[discrete]
[[breaking_75_search_changes]]
=== Search Changes
[discrete]
==== Stricter checking for wildcard queries on _index
Previously, a wildcard query on the `_index` field matched directly against the
fully-qualified index name. Now, in order to match against remote indices like
i`cluster:index`, the query must contain a colon, as in `cl*ster:inde*`. This
behavior aligns with the way indices are matched in the search endpoint.

View File

@ -0,0 +1,58 @@
---
setup:
- do:
indices.create:
index: single_doc_index
body:
settings:
index:
number_of_shards: 1
number_of_replicas: 0
---
teardown:
- do:
indices.delete:
index: single_doc_index
ignore_unavailable: true
---
"Test that queries on _index match against the correct indices.":
- do:
bulk:
refresh: true
body:
- '{"index": {"_index": "single_doc_index"}}'
- '{"f1": "local_cluster", "sort_field": 0}'
- do:
search:
rest_total_hits_as_int: true
index: "single_doc_index,my_remote_cluster:single_doc_index"
body:
query:
term:
"_index": "single_doc_index"
- match: { hits.total: 1 }
- match: { hits.hits.0._index: "single_doc_index"}
- match: { _shards.total: 2 }
- match: { _shards.successful: 2 }
- match: { _shards.skipped : 0}
- match: { _shards.failed: 0 }
- do:
search:
rest_total_hits_as_int: true
index: "single_doc_index,my_remote_cluster:single_doc_index"
body:
query:
term:
"_index": "my_remote_cluster:single_doc_index"
- match: { hits.total: 1 }
- match: { hits.hits.0._index: "my_remote_cluster:single_doc_index"}
- match: { _shards.total: 2 }
- match: { _shards.successful: 2 }
- match: { _shards.skipped : 0}
- match: { _shards.failed: 0 }

View File

@ -30,6 +30,7 @@ import org.apache.lucene.util.Constants;
import org.apache.lucene.util.SetOnce;
import org.elasticsearch.Version;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.CheckedFunction;
import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
@ -386,6 +387,7 @@ public final class IndexModule {
BigArrays bigArrays,
ThreadPool threadPool,
ScriptService scriptService,
ClusterService clusterService,
Client client,
IndicesQueryCache indicesQueryCache,
MapperRegistry mapperRegistry,
@ -411,7 +413,7 @@ public final class IndexModule {
return new IndexService(indexSettings, indexCreationContext, environment, xContentRegistry,
new SimilarityService(indexSettings, scriptService, similarities),
shardStoreDeleter, analysisRegistry, engineFactory, circuitBreakerService, bigArrays, threadPool, scriptService,
client, queryCache, directoryFactory, eventListener, readerWrapperFactory, mapperRegistry,
clusterService, client, queryCache, directoryFactory, eventListener, readerWrapperFactory, mapperRegistry,
indicesFieldDataCache, searchOperationListeners, indexOperationListeners, namedWriteableRegistry);
}

View File

@ -32,6 +32,7 @@ import org.elasticsearch.Version;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.CheckedFunction;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
@ -57,6 +58,7 @@ import org.elasticsearch.index.engine.EngineFactory;
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.SearchIndexNameMatcher;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.seqno.RetentionLeaseSyncer;
import org.elasticsearch.index.shard.IndexEventListener;
@ -134,6 +136,7 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust
private final ThreadPool threadPool;
private final BigArrays bigArrays;
private final ScriptService scriptService;
private final ClusterService clusterService;
private final Client client;
private final CircuitBreakerService circuitBreakerService;
private Supplier<Sort> indexSortSupplier;
@ -151,6 +154,7 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust
BigArrays bigArrays,
ThreadPool threadPool,
ScriptService scriptService,
ClusterService clusterService,
Client client,
QueryCache queryCache,
IndexStorePlugin.DirectoryFactory directoryFactory,
@ -201,6 +205,7 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust
this.bigArrays = bigArrays;
this.threadPool = threadPool;
this.scriptService = scriptService;
this.clusterService = clusterService;
this.client = client;
this.eventListener = eventListener;
this.nodeEnv = nodeEnv;
@ -530,9 +535,11 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust
* {@link IndexReader}-specific optimizations, such as rewriting containing range queries.
*/
public QueryShardContext newQueryShardContext(int shardId, IndexSearcher searcher, LongSupplier nowInMillis, String clusterAlias) {
SearchIndexNameMatcher indexNameMatcher = new SearchIndexNameMatcher(index().getName(), clusterAlias, clusterService);
return new QueryShardContext(
shardId, indexSettings, bigArrays, indexCache.bitsetFilterCache(), indexFieldData::getForField, mapperService(),
similarityService(), scriptService, xContentRegistry, namedWriteableRegistry, client, searcher, nowInMillis, clusterAlias);
similarityService(), scriptService, xContentRegistry, namedWriteableRegistry, client, searcher, nowInMillis, clusterAlias,
indexNameMatcher);
}
/**

View File

@ -129,11 +129,16 @@ public class IndexFieldMapper extends MetadataFieldMapper {
*/
@Override
public Query termQuery(Object value, @Nullable QueryShardContext context) {
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
String pattern = value instanceof BytesRef
? ((BytesRef) value).utf8ToString()
: value.toString();
if (context.indexMatches(pattern)) {
// 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();
} else {
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName()
+ " vs. " + value);
return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
"] doesn't match the provided value [" + value + "].");
}
}
@ -143,26 +148,29 @@ public class IndexFieldMapper extends MetadataFieldMapper {
return super.termsQuery(values, context);
}
for (Object value : values) {
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
String pattern = value instanceof BytesRef
? ((BytesRef) value).utf8ToString()
: value.toString();
if (context.indexMatches(pattern)) {
// 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("Index didn't match. Index queried: " + context.getFullyQualifiedIndex().getName()
+ " vs. " + values);
return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
"] doesn't match the provided values [" + values + "].");
}
@Override
public Query prefixQuery(String value,
@Nullable MultiTermQuery.RewriteMethod method,
QueryShardContext context) {
String indexName = context.getFullyQualifiedIndex().getName();
if (indexName.startsWith(value)) {
String pattern = value + "*";
if (context.indexMatches(pattern)) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("The index [" + indexName +
return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
"] doesn't match the provided prefix [" + value + "].");
}
}
@ -176,8 +184,8 @@ public class IndexFieldMapper extends MetadataFieldMapper {
if (pattern.matcher(indexName).matches()) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("The index [" + indexName +
"] doesn't match the provided pattern [" + value + "].");
return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName()
+ "] doesn't match the provided pattern [" + value + "].");
}
}
@ -185,20 +193,14 @@ public class IndexFieldMapper extends MetadataFieldMapper {
public Query wildcardQuery(String value,
@Nullable MultiTermQuery.RewriteMethod method,
QueryShardContext context) {
String indexName = context.getFullyQualifiedIndex().getName();
if (isSameIndex(value, indexName)) {
if (context.indexMatches(value)) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("The index [" + indexName +
"] doesn't match the provided pattern [" + value + "].");
return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName()
+ "] doesn't match the provided pattern [" + value + "].");
}
}
private boolean isSameIndex(Object value, String indexName) {
String pattern = value instanceof BytesRef ? ((BytesRef) value).utf8ToString() : value.toString();
return Regex.simpleMatch(pattern, indexName);
}
@Override
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) {
return new ConstantIndexFieldData.Builder(mapperService -> fullyQualifiedIndexName);

View File

@ -69,6 +69,7 @@ import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.LongSupplier;
import java.util.function.Predicate;
import static java.util.Collections.unmodifiableMap;
@ -93,7 +94,9 @@ public class QueryShardContext extends QueryRewriteContext {
private String[] types = Strings.EMPTY_ARRAY;
private boolean cacheable = true;
private final SetOnce<Boolean> frozen = new SetOnce<>();
private final Index fullyQualifiedIndex;
private final Predicate<String> indexNameMatcher;
public void setTypes(String... types) {
this.types = types;
@ -109,45 +112,48 @@ public class QueryShardContext extends QueryRewriteContext {
private NestedScope nestedScope;
public QueryShardContext(int shardId,
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
BiFunction<MappedFieldType, String, IndexFieldData<?>> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
String clusterAlias) {
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
BiFunction<MappedFieldType, String, IndexFieldData<?>> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
String clusterAlias,
Predicate<String> indexNameMatcher) {
this(shardId, indexSettings, bigArrays, bitsetFilterCache, indexFieldDataLookup, mapperService, similarityService,
scriptService, xContentRegistry, namedWriteableRegistry, client, searcher, nowInMillis,
scriptService, xContentRegistry, namedWriteableRegistry, client, searcher, nowInMillis, indexNameMatcher,
new Index(RemoteClusterAware.buildRemoteIndexName(clusterAlias, indexSettings.getIndex().getName()),
indexSettings.getIndex().getUUID()));
}
public QueryShardContext(QueryShardContext source) {
this(source.shardId, source.indexSettings, source.bigArrays, source.bitsetFilterCache, source.indexFieldDataService,
source.mapperService, source.similarityService, source.scriptService, source.getXContentRegistry(),
source.getWriteableRegistry(), source.client, source.searcher, source.nowInMillis, source.fullyQualifiedIndex);
source.mapperService, source.similarityService, source.scriptService, source.getXContentRegistry(),
source.getWriteableRegistry(), source.client, source.searcher, source.nowInMillis, source.indexNameMatcher,
source.fullyQualifiedIndex);
}
private QueryShardContext(int shardId,
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
BiFunction<MappedFieldType, String, IndexFieldData<?>> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
Index fullyQualifiedIndex) {
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
BiFunction<MappedFieldType, String, IndexFieldData<?>> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
Predicate<String> indexNameMatcher,
Index fullyQualifiedIndex) {
super(xContentRegistry, namedWriteableRegistry, client, nowInMillis);
this.shardId = shardId;
this.similarityService = similarityService;
@ -160,6 +166,7 @@ public class QueryShardContext extends QueryRewriteContext {
this.scriptService = scriptService;
this.indexSettings = indexSettings;
this.searcher = searcher;
this.indexNameMatcher = indexNameMatcher;
this.fullyQualifiedIndex = fullyQualifiedIndex;
}
@ -311,6 +318,14 @@ public class QueryShardContext extends QueryRewriteContext {
return indexSettings.getIndexVersionCreated();
}
/**
* Given an index pattern, checks whether it matches against the current shard. The pattern
* may represent a fully qualified index name if the search targets remote shards.
*/
public boolean indexMatches(String pattern) {
return indexNameMatcher.test(pattern);
}
public ParsedQuery toQuery(QueryBuilder queryBuilder) {
return toQuery(queryBuilder, q -> {
Query query = q.toQuery(this);

View File

@ -0,0 +1,84 @@
/*
* 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.action.support.IndicesOptions;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.transport.RemoteClusterAware;
import java.util.function.Predicate;
/**
* A predicate that checks whether an index pattern matches the current search shard target.
*/
public class SearchIndexNameMatcher implements Predicate<String> {
private final String indexName;
private final String clusterAlias;
private final ClusterService clusterService;
private final IndexNameExpressionResolver expressionResolver;
/**
* Creates a new index name matcher.
*
* @param indexName he name of the local index.
* @param clusterAlias the cluster alias of this search shard target. If it is a local target, the alias
* should be null or equal to {@link RemoteClusterAware#LOCAL_CLUSTER_GROUP_KEY}.
* @param clusterService the cluster service.
*/
public SearchIndexNameMatcher(String indexName,
String clusterAlias,
ClusterService clusterService) {
this.indexName = indexName;
this.clusterAlias = RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY.equals(clusterAlias) ? null : clusterAlias;
this.clusterService = clusterService;
this.expressionResolver = new IndexNameExpressionResolver();
}
/**
* Given an index pattern, checks whether it matches against the current shard.
*
* If this shard represents a remote shard target, then in order to match the pattern contain
* the separator ':', and must match on both the cluster alias and index name.
*/
public boolean test(String pattern) {
int separatorIndex = pattern.indexOf(RemoteClusterAware.REMOTE_CLUSTER_INDEX_SEPARATOR);
if (separatorIndex < 0) {
return clusterAlias == null && matchesIndex(pattern);
} else {
String clusterPattern = pattern.substring(0, separatorIndex);
String indexPattern = pattern.substring(separatorIndex + 1);
return Regex.simpleMatch(clusterPattern, clusterAlias) && matchesIndex(indexPattern);
}
}
private boolean matchesIndex(String pattern) {
String[] concreteIndices = expressionResolver.concreteIndexNames(
clusterService.state(), IndicesOptions.lenientExpandOpen(), pattern);
for (String index : concreteIndices) {
if (Regex.simpleMatch(index, indexName)) {
return true;
}
}
return false;
}
}

View File

@ -43,6 +43,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.routing.RecoverySource;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.CheckedFunction;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.breaker.CircuitBreaker;
@ -186,6 +187,7 @@ public class IndicesService extends AbstractLifecycleComponent
private final CircuitBreakerService circuitBreakerService;
private final BigArrays bigArrays;
private final ScriptService scriptService;
private final ClusterService clusterService;
private final Client client;
private volatile Map<String, IndexService> indices = emptyMap();
private final Map<Index, List<PendingDelete>> pendingDeletes = new HashMap<>();
@ -213,7 +215,7 @@ public class IndicesService extends AbstractLifecycleComponent
AnalysisRegistry analysisRegistry, IndexNameExpressionResolver indexNameExpressionResolver,
MapperRegistry mapperRegistry, NamedWriteableRegistry namedWriteableRegistry, ThreadPool threadPool,
IndexScopedSettings indexScopedSettings, CircuitBreakerService circuitBreakerService, BigArrays bigArrays,
ScriptService scriptService, Client client, MetaStateService metaStateService,
ScriptService scriptService, ClusterService clusterService, Client client, MetaStateService metaStateService,
Collection<Function<IndexSettings, Optional<EngineFactory>>> engineFactoryProviders,
Map<String, IndexStorePlugin.DirectoryFactory> directoryFactories) {
this.settings = settings;
@ -235,6 +237,7 @@ public class IndicesService extends AbstractLifecycleComponent
this.circuitBreakerService = circuitBreakerService;
this.bigArrays = bigArrays;
this.scriptService = scriptService;
this.clusterService = clusterService;
this.client = client;
this.indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndexFieldDataCache.Listener() {
@Override
@ -556,6 +559,7 @@ public class IndicesService extends AbstractLifecycleComponent
bigArrays,
threadPool,
scriptService,
clusterService,
client,
indicesQueryCache,
mapperRegistry,

View File

@ -427,10 +427,10 @@ public class Node implements Closeable {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
final IndicesService indicesService =
new IndicesService(settings, pluginsService, nodeEnvironment, xContentRegistry, analysisModule.getAnalysisRegistry(),
clusterModule.getIndexNameExpressionResolver(), indicesModule.getMapperRegistry(), namedWriteableRegistry,
threadPool, settingsModule.getIndexScopedSettings(), circuitBreakerService, bigArrays,
scriptModule.getScriptService(), client, metaStateService, engineFactoryProviders, indexStoreFactories);
new IndicesService(settings, pluginsService, nodeEnvironment, xContentRegistry, analysisModule.getAnalysisRegistry(),
clusterModule.getIndexNameExpressionResolver(), indicesModule.getMapperRegistry(), namedWriteableRegistry,
threadPool, settingsModule.getIndexScopedSettings(), circuitBreakerService, bigArrays, scriptModule.getScriptService(),
clusterService, client, metaStateService, engineFactoryProviders, indexStoreFactories);
final AliasValidator aliasValidator = new AliasValidator();

View File

@ -150,7 +150,7 @@ public class IndexModuleTests extends ESTestCase {
private IndexService newIndexService(IndexModule module) throws IOException {
return module.newIndexService(CREATE_INDEX, nodeEnvironment, xContentRegistry(), deleter, circuitBreakerService, bigArrays,
threadPool, scriptService, null, indicesQueryCache, mapperRegistry,
threadPool, scriptService, clusterService, null, indicesQueryCache, mapperRegistry,
new IndicesFieldDataCache(settings, listener), writableRegistry());
}

View File

@ -179,7 +179,7 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
QueryShardContext context = new QueryShardContext(0,
new IndexSettings(IndexMetaData.builder("foo").settings(indexSettings).build(), indexSettings),
BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null,
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null);
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null, null);
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
String date = "2015-10-12T14:10:55";
@ -202,7 +202,7 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
QueryShardContext context = new QueryShardContext(0,
new IndexSettings(IndexMetaData.builder("foo").settings(indexSettings).build(), indexSettings),
BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null, xContentRegistry(), writableRegistry(),
null, null, () -> nowInMillis, null);
null, null, () -> nowInMillis, null, null);
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
String date1 = "2015-10-12T14:10:55";

View File

@ -68,7 +68,7 @@ public class FieldNamesFieldTypeTests extends FieldTypeTestCase {
QueryShardContext queryShardContext = new QueryShardContext(0,
indexSettings, BigArrays.NON_RECYCLING_INSTANCE, null, null, mapperService,
null, null, null, null, null, null, () -> 0L, null);
null, null, null, null, null, null, () -> 0L, null, null);
fieldNamesFieldType.setEnabled(true);
Query termQuery = fieldNamesFieldType.termQuery("field_name", queryShardContext);
assertEquals(new TermQuery(new Term(FieldNamesFieldMapper.CONTENT_TYPE, "field_name")), termQuery);

View File

@ -21,11 +21,14 @@ package org.elasticsearch.index.mapper;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.index.Index;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.query.QueryShardContext;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.function.Predicate;
public class IndexFieldTypeTests extends FieldTypeTestCase {
@ -62,12 +65,15 @@ public class IndexFieldTypeTests extends FieldTypeTestCase {
}
private QueryShardContext createContext() {
QueryShardContext context = mock(QueryShardContext.class);
IndexMetaData indexMetaData = IndexMetaData.builder("index")
.settings(Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT))
.numberOfShards(1)
.numberOfReplicas(0)
.build();
IndexSettings indexSettings = new IndexSettings(indexMetaData, Settings.EMPTY);
Index index = new Index("index", "123");
when(context.getFullyQualifiedIndex()).thenReturn(index);
when(context.index()).thenReturn(index);
return context;
Predicate<String> indexNameMatcher = pattern -> Regex.simpleMatch(pattern, "index");
return new QueryShardContext(0, indexSettings, null, null, null, null, null, null, xContentRegistry(), writableRegistry(),
null, null, System::currentTimeMillis, null, indexNameMatcher);
}
}

View File

@ -229,7 +229,7 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
return new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null,
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null);
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null, null);
}
public void testDateRangeQueryUsingMappingFormat() {

View File

@ -371,7 +371,7 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
QueryShardContext baseContext = createShardContext();
QueryShardContext context = new QueryShardContext(baseContext.getShardId(), baseContext.getIndexSettings(),
BigArrays.NON_RECYCLING_INSTANCE, null, null, baseContext.getMapperService(),
null, scriptService, null, null, null, null, null, null);
null, scriptService, null, null, null, null, null, null, null);
String json = "{ \"intervals\" : { \"" + STRING_FIELD_NAME + "\": { " +
"\"match\" : { " +

View File

@ -18,12 +18,9 @@
*/
package org.elasticsearch.index.query;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
@ -37,7 +34,6 @@ import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.TextFieldMapper;
import org.elasticsearch.test.ESTestCase;
import org.hamcrest.Matchers;
import java.io.IOException;
import java.util.Collections;
@ -81,7 +77,6 @@ public class QueryShardContextTests extends ESTestCase {
final String clusterAlias = randomBoolean() ? null : "remote_cluster";
QueryShardContext context = createQueryShardContext(IndexMetaData.INDEX_UUID_NA_VALUE, clusterAlias);
Mapper.BuilderContext ctx = new Mapper.BuilderContext(context.getIndexSettings().getSettings(), new ContentPath());
IndexFieldMapper mapper = new IndexFieldMapper.Builder(null).build(ctx);
@ -89,21 +84,6 @@ public class QueryShardContextTests extends ESTestCase {
String expected = clusterAlias == null ? context.getIndexSettings().getIndexMetaData().getIndex().getName()
: clusterAlias + ":" + context.getIndexSettings().getIndex().getName();
assertEquals(expected, ((AbstractAtomicOrdinalsFieldData)forField.load(null)).getOrdinalsValues().lookupOrd(0).utf8ToString());
Query query = mapper.fieldType().termQuery("index", context);
if (clusterAlias == null) {
assertEquals(Queries.newMatchAllQuery(), query);
} else {
assertThat(query, Matchers.instanceOf(MatchNoDocsQuery.class));
}
query = mapper.fieldType().termQuery("remote_cluster:index", context);
if (clusterAlias != null) {
assertEquals(Queries.newMatchAllQuery(), query);
} else {
assertThat(query, Matchers.instanceOf(MatchNoDocsQuery.class));
}
query = mapper.fieldType().termQuery("something:else", context);
assertThat(query, Matchers.instanceOf(MatchNoDocsQuery.class));
}
public void testGetFullyQualifiedIndex() {
@ -133,6 +113,6 @@ public class QueryShardContextTests extends ESTestCase {
(mappedFieldType, idxName) ->
mappedFieldType.fielddataBuilder(idxName).build(indexSettings, mappedFieldType, null, null, null),
mapperService, null, null, NamedXContentRegistry.EMPTY, new NamedWriteableRegistry(Collections.emptyList()),
null, null, () -> nowInMillis, clusterAlias);
null, null, () -> nowInMillis, clusterAlias, null);
}
}

View File

@ -41,7 +41,7 @@ public class RangeQueryRewriteTests extends ESSingleNodeTestCase {
IndexReader reader = new MultiReader();
QueryRewriteContext context = new QueryShardContext(0, indexService.getIndexSettings(), BigArrays.NON_RECYCLING_INSTANCE,
null, null, indexService.mapperService(), null, null, xContentRegistry(), writableRegistry(),
null, new IndexSearcher(reader), null, null);
null, new IndexSearcher(reader), null, null, null);
RangeQueryBuilder range = new RangeQueryBuilder("foo");
assertEquals(Relation.DISJOINT, range.getRelation(context));
}
@ -57,9 +57,8 @@ public class RangeQueryRewriteTests extends ESSingleNodeTestCase {
.endObject().endObject());
indexService.mapperService().merge("type",
new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE);
QueryRewriteContext context = new QueryShardContext(0, indexService.getIndexSettings(), BigArrays.NON_RECYCLING_INSTANCE,
null, null, indexService.mapperService(), null, null,
xContentRegistry(), writableRegistry(), null, null, null, null);
QueryRewriteContext context = new QueryShardContext(0, indexService.getIndexSettings(), null, null, null,
indexService.mapperService(), null, null, xContentRegistry(), writableRegistry(), null, null, null, null, null);
RangeQueryBuilder range = new RangeQueryBuilder("foo");
// can't make assumptions on a missing reader, so it must return INTERSECT
assertEquals(Relation.INTERSECTS, range.getRelation(context));
@ -79,7 +78,7 @@ public class RangeQueryRewriteTests extends ESSingleNodeTestCase {
IndexReader reader = new MultiReader();
QueryRewriteContext context = new QueryShardContext(0, indexService.getIndexSettings(), BigArrays.NON_RECYCLING_INSTANCE,
null, null, indexService.mapperService(), null, null, xContentRegistry(), writableRegistry(),
null, new IndexSearcher(reader), null, null);
null, new IndexSearcher(reader), null, null, null);
RangeQueryBuilder range = new RangeQueryBuilder("foo");
// no values -> DISJOINT
assertEquals(Relation.DISJOINT, range.getRelation(context));

View File

@ -0,0 +1,90 @@
/*
* 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.Version;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SearchIndexNameMatcherTests extends ESTestCase {
private SearchIndexNameMatcher matcher;
private SearchIndexNameMatcher remoteMatcher;
@Before
public void setUpMatchers() {
MetaData.Builder metaDataBuilder = MetaData.builder()
.put(indexBuilder("index1").putAlias(AliasMetaData.builder("alias")))
.put(indexBuilder("index2").putAlias(AliasMetaData.builder("alias")))
.put(indexBuilder("index3"));
ClusterState state = ClusterState.builder(new ClusterName("_name")).metaData(metaDataBuilder).build();
ClusterService clusterService = mock(ClusterService.class);
when(clusterService.state()).thenReturn(state);
matcher = new SearchIndexNameMatcher("index1", "", clusterService);
remoteMatcher = new SearchIndexNameMatcher("index1", "cluster", clusterService);
}
private static IndexMetaData.Builder indexBuilder(String index) {
Settings.Builder settings = settings(Version.CURRENT).
put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0);
return IndexMetaData.builder(index).settings(settings);
}
public void testLocalIndex() {
assertTrue(matcher.test("index1"));
assertTrue(matcher.test("ind*x1"));
assertFalse(matcher.test("index2"));
assertTrue(matcher.test("alias"));
assertTrue(matcher.test("*lias"));
assertFalse(matcher.test("cluster:index1"));
}
public void testRemoteIndex() {
assertTrue(remoteMatcher.test("cluster:index1"));
assertTrue(remoteMatcher.test("cluster:ind*x1"));
assertTrue(remoteMatcher.test("*luster:ind*x1"));
assertFalse(remoteMatcher.test("cluster:index2"));
assertTrue(remoteMatcher.test("cluster:alias"));
assertTrue(remoteMatcher.test("cluster:*lias"));
assertFalse(remoteMatcher.test("index1"));
assertFalse(remoteMatcher.test("alias"));
assertFalse(remoteMatcher.test("*index1"));
assertFalse(remoteMatcher.test("*alias"));
assertFalse(remoteMatcher.test("cluster*"));
assertFalse(remoteMatcher.test("cluster*index1"));
}
}

View File

@ -27,7 +27,6 @@ import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
@ -416,15 +415,6 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
}
}
public void testIndexMetaField() throws IOException {
QueryShardContext shardContext = createShardContext();
SimpleQueryStringBuilder simpleQueryStringBuilder = new SimpleQueryStringBuilder(getIndex().getName());
simpleQueryStringBuilder.field("_index");
Query query = simpleQueryStringBuilder.toQuery(shardContext);
assertThat(query, notNullValue());
assertThat(query, instanceOf(MatchAllDocsQuery.class));
}
public void testExpandedTerms() throws Exception {
// Prefix
Query query = new SimpleQueryStringBuilder("aBc*")

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.WildcardQuery;
@ -134,20 +133,6 @@ public class WildcardQueryBuilderTests extends AbstractQueryTestCase<WildcardQue
assertEquals("[wildcard] query doesn't support multiple fields, found [user1] and [user2]", e.getMessage());
}
public void testIndexWildcard() throws IOException {
QueryShardContext context = createShardContext();
String index = context.getFullyQualifiedIndex().getName();
Query query = new WildcardQueryBuilder("_index", index).doToQuery(context);
assertThat(query instanceof MatchAllDocsQuery, equalTo(true));
query = new WildcardQueryBuilder("_index", index + "*").doToQuery(context);
assertThat(query instanceof MatchAllDocsQuery, equalTo(true));
query = new WildcardQueryBuilder("_index", "index_" + index + "*").doToQuery(context);
assertThat(query instanceof MatchNoDocsQuery, equalTo(true));
}
public void testTypeField() throws IOException {
WildcardQueryBuilder builder = QueryBuilders.wildcardQuery("_type", "doc*");
builder.doToQuery(createShardContext());

View File

@ -97,7 +97,7 @@ public class ExtendedBoundsTests extends ESTestCase {
QueryShardContext qsc = new QueryShardContext(0,
new IndexSettings(IndexMetaData.builder("foo").settings(indexSettings).build(), indexSettings),
BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null, xContentRegistry(), writableRegistry(),
null, null, () -> now, null);
null, null, () -> now, null, null);
DateFormatter formatter = DateFormatter.forPattern("dateOptionalTime");
DocValueFormat format = new DocValueFormat.DateTime(formatter, ZoneOffset.UTC, DateFieldMapper.Resolution.MILLISECONDS);

View File

@ -426,6 +426,6 @@ public class ScriptedMetricAggregatorTests extends AggregatorTestCase {
Map<String, ScriptEngine> engines = Collections.singletonMap(scriptEngine.getType(), scriptEngine);
ScriptService scriptService = new ScriptService(Settings.EMPTY, engines, ScriptModule.CORE_CONTEXTS);
return new QueryShardContext(0, indexSettings, BigArrays.NON_RECYCLING_INSTANCE, null, null, mapperService, null, scriptService,
xContentRegistry(), writableRegistry(), null, null, System::currentTimeMillis, null);
xContentRegistry(), writableRegistry(), null, null, System::currentTimeMillis, null, null);
}
}

View File

@ -280,7 +280,7 @@ public class HighlightBuilderTests extends ESTestCase {
// shard context will only need indicesQueriesRegistry for building Query objects nested in highlighter
QueryShardContext mockShardContext = new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, null, null, null, xContentRegistry(), namedWriteableRegistry,
null, null, System::currentTimeMillis, null) {
null, null, System::currentTimeMillis, null, null) {
@Override
public MappedFieldType fieldMapper(String name) {
TextFieldMapper.Builder builder = new TextFieldMapper.Builder(name);

View File

@ -144,7 +144,7 @@ public class QueryRescorerBuilderTests extends ESTestCase {
// shard context will only need indicesQueriesRegistry for building Query objects nested in query rescorer
QueryShardContext mockShardContext = new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, null, null, null,
xContentRegistry(), namedWriteableRegistry, null, null, () -> nowInMillis, null) {
xContentRegistry(), namedWriteableRegistry, null, null, () -> nowInMillis, null, null) {
@Override
public MappedFieldType fieldMapper(String name) {
TextFieldMapper.Builder builder = new TextFieldMapper.Builder(name);
@ -188,7 +188,7 @@ public class QueryRescorerBuilderTests extends ESTestCase {
// shard context will only need indicesQueriesRegistry for building Query objects nested in query rescorer
QueryShardContext mockShardContext = new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, null, null, null,
xContentRegistry(), namedWriteableRegistry, null, null, () -> nowInMillis, null) {
xContentRegistry(), namedWriteableRegistry, null, null, () -> nowInMillis, null, null) {
@Override
public MappedFieldType fieldMapper(String name) {
TextFieldMapper.Builder builder = new TextFieldMapper.Builder(name);

View File

@ -192,7 +192,7 @@ public abstract class AbstractSortTestCase<T extends SortBuilder<T>> extends EST
return builder.build(idxSettings, fieldType, new IndexFieldDataCache.None(), null, null);
};
return new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE, bitsetFilterCache, indexFieldDataLookup,
null, null, scriptService, xContentRegistry(), namedWriteableRegistry, null, null, () -> randomNonNegativeLong(), null) {
null, null, scriptService, xContentRegistry(), namedWriteableRegistry, null, null, () -> randomNonNegativeLong(), null, null) {
@Override
public MappedFieldType fieldMapper(String name) {

View File

@ -181,7 +181,7 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
((Script) invocation.getArguments()[0]).getIdOrCode()));
QueryShardContext mockShardContext = new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE, null,
null, mapperService, null, scriptService, xContentRegistry(), namedWriteableRegistry, null, null,
System::currentTimeMillis, null);
System::currentTimeMillis, null, null);
SuggestionContext suggestionContext = suggestionBuilder.build(mockShardContext);
assertEquals(toBytesRef(suggestionBuilder.text()), suggestionContext.getText());

View File

@ -976,6 +976,7 @@ public class SnapshotResiliencyTests extends ESTestCase {
new NoneCircuitBreakerService(),
bigArrays,
scriptService,
clusterService,
client,
new MetaStateService(nodeEnv, namedXContentRegistry),
Collections.emptyList(),

View File

@ -272,14 +272,14 @@ public abstract class AggregatorTestCase extends ESTestCase {
* sub-tests that need a more complex mock can overwrite this
*/
protected QueryShardContext queryShardContextMock(IndexSearcher searcher,
MapperService mapperService,
IndexSettings indexSettings,
CircuitBreakerService circuitBreakerService) {
MapperService mapperService,
IndexSettings indexSettings,
CircuitBreakerService circuitBreakerService) {
return new QueryShardContext(0, indexSettings, BigArrays.NON_RECYCLING_INSTANCE, null,
getIndexFieldDataLookup(mapperService, circuitBreakerService),
mapperService, null, getMockScriptService(), xContentRegistry(),
writableRegistry(), null, searcher, System::currentTimeMillis, null);
writableRegistry(), null, searcher, System::currentTimeMillis, null, null);
}
/**

View File

@ -407,7 +407,7 @@ public abstract class AbstractBuilderTestCase extends ESTestCase {
QueryShardContext createShardContext(IndexSearcher searcher) {
return new QueryShardContext(0, idxSettings, BigArrays.NON_RECYCLING_INSTANCE, bitsetFilterCache,
indexFieldDataService::getForField, mapperService, similarityService, scriptService, xContentRegistry,
namedWriteableRegistry, this.client, searcher, () -> nowInMillis, null);
namedWriteableRegistry, this.client, searcher, () -> nowInMillis, null, null);
}
ScriptModule createScriptModule(List<ScriptPlugin> scriptPlugins) {

View File

@ -43,7 +43,7 @@ public class MockSearchServiceTests extends ESTestCase {
final long nowInMillis = randomNonNegativeLong();
SearchContext s = new TestSearchContext(new QueryShardContext(0,
new IndexSettings(EMPTY_INDEX_METADATA, Settings.EMPTY), BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null,
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null)) {
xContentRegistry(), writableRegistry(), null, null, () -> nowInMillis, null, null)) {
@Override
public SearchShardTarget shardTarget() {

View File

@ -241,7 +241,7 @@ public class DocumentSubsetBitsetCacheTests extends ESTestCase {
final QueryShardContext context = new QueryShardContext(shardId.id(), indexSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, mapperService, null, null, xContentRegistry(), writableRegistry(),
client, new IndexSearcher(directoryReader), () -> nowInMillis, null);
client, new IndexSearcher(directoryReader), () -> nowInMillis, null, null);
body.accept(context, leaf);
}
}

View File

@ -85,7 +85,7 @@ public class SecurityIndexReaderWrapperIntegrationTests extends AbstractBuilderT
final long nowInMillis = randomNonNegativeLong();
QueryShardContext realQueryShardContext = new QueryShardContext(shardId.id(), indexSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, mapperService, null, null, xContentRegistry(), writableRegistry(),
client, null, () -> nowInMillis, null);
client, null, () -> nowInMillis, null, null);
QueryShardContext queryShardContext = spy(realQueryShardContext);
DocumentSubsetBitsetCache bitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
@ -200,7 +200,7 @@ public class SecurityIndexReaderWrapperIntegrationTests extends AbstractBuilderT
final long nowInMillis = randomNonNegativeLong();
QueryShardContext realQueryShardContext = new QueryShardContext(shardId.id(), indexSettings, BigArrays.NON_RECYCLING_INSTANCE,
null, null, mapperService, null, null, xContentRegistry(), writableRegistry(),
client, null, () -> nowInMillis, null);
client, null, () -> nowInMillis, null, null);
QueryShardContext queryShardContext = spy(realQueryShardContext);
DocumentSubsetBitsetCache bitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);

View File

@ -93,7 +93,7 @@ public class RollupIndexerIndexingTests extends AggregatorTestCase {
settings = createIndexSettings();
queryShardContext = new QueryShardContext(0, settings,
BigArrays.NON_RECYCLING_INSTANCE, null, null, null, null, null,
null, null, null, null, () -> 0L, null);
null, null, null, null, () -> 0L, null, null);
}
public void testSimpleDateHisto() throws Exception {