Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.index.query;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.join.BitSetProducer;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.lucene.util.SetOnce;
import org.opensearch.Version;
import org.opensearch.action.ActionListener;
import org.opensearch.client.Client;
import org.opensearch.common.CheckedFunction;
import org.opensearch.common.ParsingException;
import org.opensearch.common.Strings;
import org.opensearch.common.TriFunction;
import org.opensearch.common.io.stream.NamedWriteableRegistry;
import org.opensearch.common.lucene.search.Queries;
import org.opensearch.common.util.BigArrays;
import org.opensearch.common.xcontent.NamedXContentRegistry;
import org.opensearch.common.xcontent.XContentParser;
import org.opensearch.index.Index;
import org.opensearch.index.IndexSettings;
import org.opensearch.index.IndexSortConfig;
import org.opensearch.index.analysis.IndexAnalyzers;
import org.opensearch.index.cache.bitset.BitsetFilterCache;
import org.opensearch.index.fielddata.IndexFieldData;
import org.opensearch.index.mapper.ContentPath;
import org.opensearch.index.mapper.DocumentMapper;
import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.Mapper;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ObjectMapper;
import org.opensearch.index.mapper.TextFieldMapper;
import org.opensearch.index.query.support.NestedScope;
import org.opensearch.index.similarity.SimilarityService;
import org.opensearch.script.Script;
import org.opensearch.script.ScriptContext;
import org.opensearch.script.ScriptFactory;
import org.opensearch.script.ScriptService;
import org.opensearch.search.aggregations.support.AggregationUsageService;
import org.opensearch.search.aggregations.support.ValuesSourceRegistry;
import org.opensearch.search.lookup.SearchLookup;
import org.opensearch.transport.RemoteClusterAware;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
import java.util.function.LongSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.util.Collections.unmodifiableMap;
/**
* Context object used to create lucene queries on the shard level.
*/
public class QueryShardContext extends QueryRewriteContext {
private final ScriptService scriptService;
private final IndexSettings indexSettings;
private final BigArrays bigArrays;
private final MapperService mapperService;
private final SimilarityService similarityService;
private final BitsetFilterCache bitsetFilterCache;
private final TriFunction, IndexFieldData> indexFieldDataService;
private final int shardId;
private final IndexSearcher searcher;
private String[] types = Strings.EMPTY_ARRAY;
private boolean cacheable = true;
private final SetOnce frozen = new SetOnce<>();
private final Index fullyQualifiedIndex;
private final Predicate indexNameMatcher;
private final BooleanSupplier allowExpensiveQueries;
public void setTypes(String... types) {
this.types = types;
}
public String[] getTypes() {
return types;
}
private final Map namedQueries = new HashMap<>();
private boolean allowUnmappedFields;
private boolean mapUnmappedFieldAsString;
private NestedScope nestedScope;
private final ValuesSourceRegistry valuesSourceRegistry;
public QueryShardContext(
int shardId,
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
TriFunction, IndexFieldData> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
String clusterAlias,
Predicate indexNameMatcher,
BooleanSupplier allowExpensiveQueries,
ValuesSourceRegistry valuesSourceRegistry
) {
this(
shardId,
indexSettings,
bigArrays,
bitsetFilterCache,
indexFieldDataLookup,
mapperService,
similarityService,
scriptService,
xContentRegistry,
namedWriteableRegistry,
client,
searcher,
nowInMillis,
indexNameMatcher,
new Index(
RemoteClusterAware.buildRemoteIndexName(clusterAlias, indexSettings.getIndex().getName()),
indexSettings.getIndex().getUUID()
),
allowExpensiveQueries,
valuesSourceRegistry
);
}
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.indexNameMatcher,
source.fullyQualifiedIndex,
source.allowExpensiveQueries,
source.valuesSourceRegistry
);
}
private QueryShardContext(
int shardId,
IndexSettings indexSettings,
BigArrays bigArrays,
BitsetFilterCache bitsetFilterCache,
TriFunction, IndexFieldData> indexFieldDataLookup,
MapperService mapperService,
SimilarityService similarityService,
ScriptService scriptService,
NamedXContentRegistry xContentRegistry,
NamedWriteableRegistry namedWriteableRegistry,
Client client,
IndexSearcher searcher,
LongSupplier nowInMillis,
Predicate indexNameMatcher,
Index fullyQualifiedIndex,
BooleanSupplier allowExpensiveQueries,
ValuesSourceRegistry valuesSourceRegistry
) {
super(xContentRegistry, namedWriteableRegistry, client, nowInMillis);
this.shardId = shardId;
this.similarityService = similarityService;
this.mapperService = mapperService;
this.bigArrays = bigArrays;
this.bitsetFilterCache = bitsetFilterCache;
this.indexFieldDataService = indexFieldDataLookup;
this.allowUnmappedFields = indexSettings.isDefaultAllowUnmappedFields();
this.nestedScope = new NestedScope();
this.scriptService = scriptService;
this.indexSettings = indexSettings;
this.searcher = searcher;
this.indexNameMatcher = indexNameMatcher;
this.fullyQualifiedIndex = fullyQualifiedIndex;
this.allowExpensiveQueries = allowExpensiveQueries;
this.valuesSourceRegistry = valuesSourceRegistry;
}
private void reset() {
allowUnmappedFields = indexSettings.isDefaultAllowUnmappedFields();
this.lookup = null;
this.namedQueries.clear();
this.nestedScope = new NestedScope();
}
public IndexAnalyzers getIndexAnalyzers() {
return mapperService.getIndexAnalyzers();
}
public Similarity getSearchSimilarity() {
return similarityService != null ? similarityService.similarity(mapperService) : null;
}
public List defaultFields() {
return indexSettings.getDefaultFields();
}
public boolean queryStringLenient() {
return indexSettings.isQueryStringLenient();
}
public boolean queryStringAnalyzeWildcard() {
return indexSettings.isQueryStringAnalyzeWildcard();
}
public boolean queryStringAllowLeadingWildcard() {
return indexSettings.isQueryStringAllowLeadingWildcard();
}
public BitSetProducer bitsetFilter(Query filter) {
return bitsetFilterCache.getBitSetProducer(filter);
}
public boolean allowExpensiveQueries() {
return allowExpensiveQueries.getAsBoolean();
}
public > IFD getForField(MappedFieldType fieldType) {
return (IFD) indexFieldDataService.apply(
fieldType,
fullyQualifiedIndex.getName(),
() -> this.lookup().forkAndTrackFieldReferences(fieldType.name())
);
}
public void addNamedQuery(String name, Query query) {
if (query != null) {
namedQueries.put(name, query);
}
}
public Map copyNamedQueries() {
// This might be a good use case for CopyOnWriteHashMap
return unmodifiableMap(new HashMap<>(namedQueries));
}
/**
* Returns all the fields that match a given pattern. If prefixed with a
* type then the fields will be returned with a type prefix.
*/
public Set simpleMatchToIndexNames(String pattern) {
return mapperService.simpleMatchToFullName(pattern);
}
public MappedFieldType fieldMapper(String name) {
return failIfFieldMappingNotFound(name, mapperService.fieldType(name));
}
public ObjectMapper getObjectMapper(String name) {
return mapperService.getObjectMapper(name);
}
/**
* Returns s {@link DocumentMapper} instance for the given type.
* Delegates to {@link MapperService#documentMapper(String)}
*/
public DocumentMapper documentMapper(String type) {
return mapperService.documentMapper(type);
}
/**
* Gets the search analyzer for the given field, or the default if there is none present for the field
* TODO: remove this by moving defaults into mappers themselves
*/
public Analyzer getSearchAnalyzer(MappedFieldType fieldType) {
if (fieldType.getTextSearchInfo().getSearchAnalyzer() != null) {
return fieldType.getTextSearchInfo().getSearchAnalyzer();
}
return getMapperService().searchAnalyzer();
}
/**
* Gets the search quote analyzer for the given field, or the default if there is none present for the field
* TODO: remove this by moving defaults into mappers themselves
*/
public Analyzer getSearchQuoteAnalyzer(MappedFieldType fieldType) {
if (fieldType.getTextSearchInfo().getSearchQuoteAnalyzer() != null) {
return fieldType.getTextSearchInfo().getSearchQuoteAnalyzer();
}
return getMapperService().searchQuoteAnalyzer();
}
public ValuesSourceRegistry getValuesSourceRegistry() {
return valuesSourceRegistry;
}
public void setAllowUnmappedFields(boolean allowUnmappedFields) {
this.allowUnmappedFields = allowUnmappedFields;
}
public void setMapUnmappedFieldAsString(boolean mapUnmappedFieldAsString) {
this.mapUnmappedFieldAsString = mapUnmappedFieldAsString;
}
MappedFieldType failIfFieldMappingNotFound(String name, MappedFieldType fieldMapping) {
if (fieldMapping != null || allowUnmappedFields) {
return fieldMapping;
} else if (mapUnmappedFieldAsString) {
TextFieldMapper.Builder builder = new TextFieldMapper.Builder(name, mapperService.getIndexAnalyzers());
return builder.build(new Mapper.BuilderContext(indexSettings.getSettings(), new ContentPath(1))).fieldType();
} else {
throw new QueryShardException(this, "No field mapping can be found for the field with name [{}]", name);
}
}
/**
* Returns the narrowed down explicit types, or, if not set, all types.
*/
public Collection queryTypes() {
String[] types = getTypes();
if (types == null || types.length == 0 || (types.length == 1 && types[0].equals("_all"))) {
DocumentMapper mapper = getMapperService().documentMapper();
return mapper == null ? Collections.emptyList() : Collections.singleton(mapper.type());
}
return Arrays.asList(types);
}
private SearchLookup lookup = null;
/**
* Get the lookup to use during the search.
*/
public SearchLookup lookup() {
if (this.lookup == null) {
this.lookup = new SearchLookup(
getMapperService(),
(fieldType, searchLookup) -> indexFieldDataService.apply(fieldType, fullyQualifiedIndex.getName(), searchLookup),
types
);
}
return this.lookup;
}
/**
* Build a lookup customized for the fetch phase. Use {@link #lookup()}
* in other phases.
*/
public SearchLookup newFetchLookup() {
/*
* Real customization coming soon, I promise!
*/
return new SearchLookup(
getMapperService(),
(fieldType, searchLookup) -> indexFieldDataService.apply(fieldType, fullyQualifiedIndex.getName(), searchLookup),
types
);
}
public NestedScope nestedScope() {
return nestedScope;
}
public Version indexVersionCreated() {
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 boolean indexSortedOnField(String field) {
IndexSortConfig indexSortConfig = indexSettings.getIndexSortConfig();
return indexSortConfig.hasPrimarySortOnField(field);
}
public ParsedQuery toQuery(QueryBuilder queryBuilder) {
return toQuery(queryBuilder, q -> {
Query query = q.toQuery(this);
if (query == null) {
query = Queries.newMatchNoDocsQuery("No query left after rewrite.");
}
return query;
});
}
private ParsedQuery toQuery(QueryBuilder queryBuilder, CheckedFunction filterOrQuery) {
reset();
try {
QueryBuilder rewriteQuery = Rewriteable.rewrite(queryBuilder, this, true);
return new ParsedQuery(filterOrQuery.apply(rewriteQuery), copyNamedQueries());
} catch (QueryShardException | ParsingException e) {
throw e;
} catch (Exception e) {
throw new QueryShardException(this, "failed to create query: {}", e, e.getMessage());
} finally {
reset();
}
}
public Index index() {
return indexSettings.getIndex();
}
/** Compile script using script service */
public FactoryType compile(Script script, ScriptContext context) {
FactoryType factory = scriptService.compile(script, context);
if (factory instanceof ScriptFactory && ((ScriptFactory) factory).isResultDeterministic() == false) {
failIfFrozen();
}
return factory;
}
/**
* if this method is called the query context will throw exception if methods are accessed
* that could yield different results across executions like {@link #getClient()}
*/
public final void freezeContext() {
this.frozen.set(Boolean.TRUE);
}
/**
* This method fails if {@link #freezeContext()} is called before on this
* context. This is used to seal.
*
* This methods and all methods that call it should be final to ensure that
* setting the request as not cacheable and the freezing behaviour of this
* class cannot be bypassed. This is important so we can trust when this
* class says a request can be cached.
*/
protected final void failIfFrozen() {
this.cacheable = false;
if (frozen.get() == Boolean.TRUE) {
throw new IllegalArgumentException("features that prevent cachability are disabled on this context");
} else {
assert frozen.get() == null : frozen.get();
}
}
@Override
public void registerAsyncAction(BiConsumer> asyncAction) {
failIfFrozen();
super.registerAsyncAction(asyncAction);
}
@Override
public void executeAsyncActions(ActionListener listener) {
failIfFrozen();
super.executeAsyncActions(listener);
}
/**
* Returns true iff the result of the processed search request is cacheable. Otherwise false
*/
public final boolean isCacheable() {
return cacheable;
}
/**
* Returns the shard ID this context was created for.
*/
public int getShardId() {
return shardId;
}
@Override
public final long nowInMillis() {
failIfFrozen();
return super.nowInMillis();
}
public Client getClient() {
failIfFrozen(); // we somebody uses a terms filter with lookup for instance can't be cached...
return client;
}
public QueryBuilder parseInnerQueryBuilder(XContentParser parser) throws IOException {
return AbstractQueryBuilder.parseInnerQueryBuilder(parser);
}
@Override
public final QueryShardContext convertToShardContext() {
return this;
}
/**
* Returns the index settings for this context. This might return null if the
* context has not index scope.
*/
public IndexSettings getIndexSettings() {
return indexSettings;
}
/**
* Return the MapperService.
*/
public MapperService getMapperService() {
return mapperService;
}
/** Return the current {@link IndexReader}, or {@code null} if no index reader is available,
* for instance if this rewrite context is used to index queries (percolation). */
public IndexReader getIndexReader() {
return searcher == null ? null : searcher.getIndexReader();
}
/** Return the current {@link IndexSearcher}, or {@code null} if no index reader is available,
* for instance if this rewrite context is used to index queries (percolation). */
public IndexSearcher searcher() {
return searcher;
}
/**
* Returns the fully qualified index including a remote cluster alias if applicable, and the index uuid
*/
public Index getFullyQualifiedIndex() {
return fullyQualifiedIndex;
}
/**
* Return the {@link BigArrays} instance for this node.
*/
public BigArrays bigArrays() {
return bigArrays;
}
public SimilarityService getSimilarityService() {
return similarityService;
}
public BitsetFilterCache getBitsetFilterCache() {
return bitsetFilterCache;
}
public AggregationUsageService getUsageService() {
return valuesSourceRegistry.getUsageService();
}
}