|
@@ -27,14 +27,19 @@ import org.apache.lucene.search.join.BitSetProducer;
|
|
|
import org.apache.lucene.search.similarities.Similarity;
|
|
|
import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.client.Client;
|
|
|
-import org.elasticsearch.cluster.metadata.IndexMetaData;
|
|
|
+import org.elasticsearch.common.Nullable;
|
|
|
import org.elasticsearch.common.ParseFieldMatcher;
|
|
|
+import org.elasticsearch.common.ParsingException;
|
|
|
import org.elasticsearch.common.bytes.BytesReference;
|
|
|
-import org.elasticsearch.common.settings.Settings;
|
|
|
+import org.elasticsearch.common.lucene.search.Queries;
|
|
|
+import org.elasticsearch.common.xcontent.XContentFactory;
|
|
|
import org.elasticsearch.common.xcontent.XContentParser;
|
|
|
import org.elasticsearch.index.Index;
|
|
|
+import org.elasticsearch.index.IndexSettings;
|
|
|
import org.elasticsearch.index.analysis.AnalysisService;
|
|
|
+import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
|
|
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
|
|
+import org.elasticsearch.index.fielddata.IndexFieldDataService;
|
|
|
import org.elasticsearch.index.mapper.ContentPath;
|
|
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
|
|
import org.elasticsearch.index.mapper.Mapper;
|
|
@@ -42,15 +47,20 @@ import org.elasticsearch.index.mapper.MapperBuilders;
|
|
|
import org.elasticsearch.index.mapper.MapperService;
|
|
|
import org.elasticsearch.index.mapper.core.StringFieldMapper;
|
|
|
import org.elasticsearch.index.mapper.object.ObjectMapper;
|
|
|
+import org.elasticsearch.index.query.support.InnerHitsQueryParserHelper;
|
|
|
import org.elasticsearch.index.query.support.NestedScope;
|
|
|
+import org.elasticsearch.index.similarity.SimilarityService;
|
|
|
+import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
|
|
import org.elasticsearch.script.ExecutableScript;
|
|
|
import org.elasticsearch.script.ScriptContext;
|
|
|
import org.elasticsearch.script.ScriptService;
|
|
|
import org.elasticsearch.script.Template;
|
|
|
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
|
|
|
+import org.elasticsearch.search.fetch.innerhits.InnerHitsSubSearchContext;
|
|
|
import org.elasticsearch.search.internal.SearchContext;
|
|
|
import org.elasticsearch.search.lookup.SearchLookup;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collection;
|
|
|
import java.util.HashMap;
|
|
@@ -63,7 +73,14 @@ import static java.util.Collections.unmodifiableMap;
|
|
|
*/
|
|
|
public class QueryShardContext {
|
|
|
|
|
|
- private static ThreadLocal<String[]> typesContext = new ThreadLocal<>();
|
|
|
+ private static final ThreadLocal<String[]> typesContext = new ThreadLocal<>();
|
|
|
+ private final MapperService mapperService;
|
|
|
+ private final ScriptService scriptService;
|
|
|
+ private final SimilarityService similarityService;
|
|
|
+ private final BitsetFilterCache bitsetFilterCache;
|
|
|
+ private final IndexFieldDataService indexFieldDataService;
|
|
|
+ private final IndexSettings indexSettings;
|
|
|
+ private final Client client;
|
|
|
|
|
|
public static void setTypes(String[] types) {
|
|
|
typesContext.set(types);
|
|
@@ -83,28 +100,36 @@ public class QueryShardContext {
|
|
|
typesContext.remove();
|
|
|
}
|
|
|
|
|
|
- private final Version indexVersionCreated;
|
|
|
-
|
|
|
- private final IndexQueryParserService indexQueryParser;
|
|
|
-
|
|
|
private final Map<String, Query> namedQueries = new HashMap<>();
|
|
|
-
|
|
|
private final MapperQueryParser queryParser = new MapperQueryParser(this);
|
|
|
-
|
|
|
+ private final IndicesQueriesRegistry indicesQueriesRegistry;
|
|
|
private boolean allowUnmappedFields;
|
|
|
-
|
|
|
private boolean mapUnmappedFieldAsString;
|
|
|
-
|
|
|
private NestedScope nestedScope;
|
|
|
-
|
|
|
private QueryParseContext parseContext;
|
|
|
+ boolean isFilter; // pkg private for testing
|
|
|
|
|
|
- boolean isFilter;
|
|
|
+ public QueryShardContext(IndexSettings indexSettings, Client client, BitsetFilterCache bitsetFilterCache, IndexFieldDataService indexFieldDataService, MapperService mapperService, SimilarityService similarityService, ScriptService scriptService,
|
|
|
+ final IndicesQueriesRegistry indicesQueriesRegistry) {
|
|
|
+ this.indexSettings = indexSettings;
|
|
|
+ this.scriptService = scriptService;
|
|
|
+ this.client = client;
|
|
|
+ this.similarityService = similarityService;
|
|
|
+ this.mapperService = mapperService;
|
|
|
+ this.bitsetFilterCache = bitsetFilterCache;
|
|
|
+ this.indexFieldDataService = indexFieldDataService;
|
|
|
+ this.allowUnmappedFields = indexSettings.isDefaultAllowUnmappedFields();
|
|
|
+ this.indicesQueriesRegistry = indicesQueriesRegistry;
|
|
|
+ this.parseContext = new QueryParseContext(indicesQueriesRegistry);
|
|
|
+ }
|
|
|
|
|
|
- public QueryShardContext(IndexQueryParserService indexQueryParser) {
|
|
|
- this.indexVersionCreated = indexQueryParser.getIndexCreatedVersion();
|
|
|
- this.indexQueryParser = indexQueryParser;
|
|
|
- this.parseContext = new QueryParseContext(indexQueryParser.indicesQueriesRegistry());
|
|
|
+ public QueryShardContext(QueryShardContext source) {
|
|
|
+ this(source.indexSettings, source.client, source.bitsetFilterCache, source.indexFieldDataService, source.mapperService, source.similarityService, source.scriptService, source.indicesQueriesRegistry);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public QueryShardContext clone() {
|
|
|
+ return new QueryShardContext(indexSettings, client, bitsetFilterCache, indexFieldDataService, mapperService, similarityService, scriptService, indicesQueriesRegistry);
|
|
|
}
|
|
|
|
|
|
public void parseFieldMatcher(ParseFieldMatcher parseFieldMatcher) {
|
|
@@ -116,11 +141,12 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public void reset() {
|
|
|
- allowUnmappedFields = indexQueryParser.defaultAllowUnmappedFields();
|
|
|
+ allowUnmappedFields = indexSettings.isDefaultAllowUnmappedFields();
|
|
|
this.parseFieldMatcher(ParseFieldMatcher.EMPTY);
|
|
|
this.lookup = null;
|
|
|
this.namedQueries.clear();
|
|
|
this.nestedScope = new NestedScope();
|
|
|
+ this.isFilter = false;
|
|
|
}
|
|
|
|
|
|
public void reset(XContentParser jp) {
|
|
@@ -129,43 +155,43 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public Index index() {
|
|
|
- return this.indexQueryParser.index();
|
|
|
+ return this.mapperService.getIndexSettings().getIndex();
|
|
|
}
|
|
|
|
|
|
- public IndexQueryParserService indexQueryParserService() {
|
|
|
- return indexQueryParser;
|
|
|
+ public InnerHitsSubSearchContext getInnerHitsContext(XContentParser parser) throws IOException {
|
|
|
+ return InnerHitsQueryParserHelper.parse(parser);
|
|
|
}
|
|
|
|
|
|
- public AnalysisService analysisService() {
|
|
|
- return indexQueryParser.analysisService;
|
|
|
+ public AnalysisService getAnalysisService() {
|
|
|
+ return mapperService.analysisService();
|
|
|
}
|
|
|
|
|
|
- public ScriptService scriptService() {
|
|
|
- return indexQueryParser.scriptService;
|
|
|
+ public ScriptService getScriptService() {
|
|
|
+ return scriptService;
|
|
|
}
|
|
|
|
|
|
- public MapperService mapperService() {
|
|
|
- return indexQueryParser.mapperService;
|
|
|
+ public MapperService getMapperService() {
|
|
|
+ return mapperService;
|
|
|
}
|
|
|
|
|
|
- public Similarity searchSimilarity() {
|
|
|
- return indexQueryParser.similarityService != null ? indexQueryParser.similarityService.similarity(indexQueryParser.mapperService) : null;
|
|
|
+ public Similarity getSearchSimilarity() {
|
|
|
+ return similarityService != null ? similarityService.similarity(mapperService) : null;
|
|
|
}
|
|
|
|
|
|
public String defaultField() {
|
|
|
- return indexQueryParser.defaultField();
|
|
|
+ return indexSettings.getDefaultField();
|
|
|
}
|
|
|
|
|
|
public boolean queryStringLenient() {
|
|
|
- return indexQueryParser.queryStringLenient();
|
|
|
+ return indexSettings.isQueryStringLenient();
|
|
|
}
|
|
|
|
|
|
public boolean queryStringAnalyzeWildcard() {
|
|
|
- return indexQueryParser.queryStringAnalyzeWildcard();
|
|
|
+ return indexSettings.isQueryStringAnalyzeWildcard();
|
|
|
}
|
|
|
|
|
|
public boolean queryStringAllowLeadingWildcard() {
|
|
|
- return indexQueryParser.queryStringAllowLeadingWildcard();
|
|
|
+ return indexSettings.isQueryStringAllowLeadingWildcard();
|
|
|
}
|
|
|
|
|
|
public MapperQueryParser queryParser(QueryParserSettings settings) {
|
|
@@ -174,11 +200,11 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public BitSetProducer bitsetFilter(Query filter) {
|
|
|
- return indexQueryParser.bitsetFilterCache.getBitSetProducer(filter);
|
|
|
+ return bitsetFilterCache.getBitSetProducer(filter);
|
|
|
}
|
|
|
|
|
|
public <IFD extends IndexFieldData<?>> IFD getForField(MappedFieldType mapper) {
|
|
|
- return indexQueryParser.fieldDataService.getForField(mapper);
|
|
|
+ return indexFieldDataService.getForField(mapper);
|
|
|
}
|
|
|
|
|
|
public void addNamedQuery(String name, Query query) {
|
|
@@ -211,7 +237,7 @@ public class QueryShardContext {
|
|
|
|
|
|
InnerHitsContext innerHitsContext;
|
|
|
if (sc.innerHits() == null) {
|
|
|
- innerHitsContext = new InnerHitsContext(new HashMap<String, InnerHitsContext.BaseInnerHits>());
|
|
|
+ innerHitsContext = new InnerHitsContext(new HashMap<>());
|
|
|
sc.innerHits(innerHitsContext);
|
|
|
} else {
|
|
|
innerHitsContext = sc.innerHits();
|
|
@@ -220,15 +246,15 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public Collection<String> simpleMatchToIndexNames(String pattern) {
|
|
|
- return indexQueryParser.mapperService.simpleMatchToIndexNames(pattern);
|
|
|
+ return mapperService.simpleMatchToIndexNames(pattern);
|
|
|
}
|
|
|
|
|
|
public MappedFieldType fieldMapper(String name) {
|
|
|
- return failIfFieldMappingNotFound(name, indexQueryParser.mapperService.smartNameFieldType(name, getTypes()));
|
|
|
+ return failIfFieldMappingNotFound(name, mapperService.smartNameFieldType(name, getTypes()));
|
|
|
}
|
|
|
|
|
|
public ObjectMapper getObjectMapper(String name) {
|
|
|
- return indexQueryParser.mapperService.getObjectMapper(name, getTypes());
|
|
|
+ return mapperService.getObjectMapper(name, getTypes());
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -239,7 +265,7 @@ public class QueryShardContext {
|
|
|
if (fieldType.searchAnalyzer() != null) {
|
|
|
return fieldType.searchAnalyzer();
|
|
|
}
|
|
|
- return mapperService().searchAnalyzer();
|
|
|
+ return getMapperService().searchAnalyzer();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -250,7 +276,7 @@ public class QueryShardContext {
|
|
|
if (fieldType.searchQuoteAnalyzer() != null) {
|
|
|
return fieldType.searchQuoteAnalyzer();
|
|
|
}
|
|
|
- return mapperService().searchQuoteAnalyzer();
|
|
|
+ return getMapperService().searchQuoteAnalyzer();
|
|
|
}
|
|
|
|
|
|
public void setAllowUnmappedFields(boolean allowUnmappedFields) {
|
|
@@ -266,11 +292,9 @@ public class QueryShardContext {
|
|
|
return fieldMapping;
|
|
|
} else if (mapUnmappedFieldAsString) {
|
|
|
StringFieldMapper.Builder builder = MapperBuilders.stringField(name);
|
|
|
- // it would be better to pass the real index settings, but they are not easily accessible from here...
|
|
|
- Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, indexQueryParser.getIndexCreatedVersion()).build();
|
|
|
- return builder.build(new Mapper.BuilderContext(settings, new ContentPath(1))).fieldType();
|
|
|
+ return builder.build(new Mapper.BuilderContext(indexSettings.getSettings(), new ContentPath(1))).fieldType();
|
|
|
} else {
|
|
|
- Version indexCreatedVersion = indexQueryParser.getIndexCreatedVersion();
|
|
|
+ Version indexCreatedVersion = indexSettings.getIndexVersionCreated();
|
|
|
if (fieldMapping == null && indexCreatedVersion.onOrAfter(Version.V_1_4_0_Beta1)) {
|
|
|
throw new QueryShardException(this, "Strict field resolution and no field mapping can be found for the field with name ["
|
|
|
+ name + "]");
|
|
@@ -286,10 +310,10 @@ public class QueryShardContext {
|
|
|
public Collection<String> queryTypes() {
|
|
|
String[] types = getTypes();
|
|
|
if (types == null || types.length == 0) {
|
|
|
- return mapperService().types();
|
|
|
+ return getMapperService().types();
|
|
|
}
|
|
|
if (types.length == 1 && types[0].equals("_all")) {
|
|
|
- return mapperService().types();
|
|
|
+ return getMapperService().types();
|
|
|
}
|
|
|
return Arrays.asList(types);
|
|
|
}
|
|
@@ -302,7 +326,7 @@ public class QueryShardContext {
|
|
|
return current.lookup();
|
|
|
}
|
|
|
if (lookup == null) {
|
|
|
- lookup = new SearchLookup(mapperService(), indexQueryParser.fieldDataService, null);
|
|
|
+ lookup = new SearchLookup(getMapperService(), indexFieldDataService, null);
|
|
|
}
|
|
|
return lookup;
|
|
|
}
|
|
@@ -320,7 +344,7 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public Version indexVersionCreated() {
|
|
|
- return indexVersionCreated;
|
|
|
+ return indexSettings.getIndexVersionCreated();
|
|
|
}
|
|
|
|
|
|
public QueryParseContext parseContext() {
|
|
@@ -328,18 +352,105 @@ public class QueryShardContext {
|
|
|
}
|
|
|
|
|
|
public boolean matchesIndices(String... indices) {
|
|
|
- return this.indexQueryParser.matchesIndices(indices);
|
|
|
+ for (String index : indices) {
|
|
|
+ if (indexSettings.matchesIndexName(index)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Executes the given template, and returns the response.
|
|
|
*/
|
|
|
public BytesReference executeQueryTemplate(Template template, SearchContext searchContext) {
|
|
|
- ExecutableScript executable = scriptService().executable(template, ScriptContext.Standard.SEARCH, searchContext);
|
|
|
+ ExecutableScript executable = getScriptService().executable(template, ScriptContext.Standard.SEARCH, searchContext);
|
|
|
return (BytesReference) executable.run();
|
|
|
}
|
|
|
|
|
|
public Client getClient() {
|
|
|
- return indexQueryParser.getClient();
|
|
|
+ return client;
|
|
|
+ }
|
|
|
+
|
|
|
+ public ParsedQuery parse(BytesReference source) {
|
|
|
+ XContentParser parser = null;
|
|
|
+ try {
|
|
|
+ parser = XContentFactory.xContent(source).createParser(source);
|
|
|
+ return innerParse(parser);
|
|
|
+ } catch (ParsingException e) {
|
|
|
+ throw e;
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ParsingException(parser == null ? null : parser.getTokenLocation(), "Failed to parse", e);
|
|
|
+ } finally {
|
|
|
+ if (parser != null) {
|
|
|
+ parser.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ public ParsedQuery parse(XContentParser parser) {
|
|
|
+ try {
|
|
|
+ return innerParse(parser);
|
|
|
+ } catch(IOException e) {
|
|
|
+ throw new ParsingException(parser.getTokenLocation(), "Failed to parse", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Parses an inner filter, returning null if the filter should be ignored.
|
|
|
+ */
|
|
|
+ @Nullable
|
|
|
+ public ParsedQuery parseInnerFilter(XContentParser parser) throws IOException {
|
|
|
+ reset(parser);
|
|
|
+ try {
|
|
|
+ parseFieldMatcher(indexSettings.getParseFieldMatcher());
|
|
|
+ Query filter = parseContext().parseInnerQueryBuilder().toFilter(this);
|
|
|
+ if (filter == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return new ParsedQuery(filter, copyNamedQueries());
|
|
|
+ } finally {
|
|
|
+ reset(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private ParsedQuery innerParse(XContentParser parser) throws IOException, QueryShardException {
|
|
|
+ reset(parser);
|
|
|
+ try {
|
|
|
+ parseFieldMatcher(indexSettings.getParseFieldMatcher());
|
|
|
+ Query query = parseInnerQuery();
|
|
|
+ return new ParsedQuery(query, copyNamedQueries());
|
|
|
+ } finally {
|
|
|
+ reset(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Query parseInnerQuery() throws IOException {
|
|
|
+ return toQuery(this.parseContext().parseInnerQueryBuilder(), this);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ParsedQuery toQuery(QueryBuilder<?> queryBuilder) {
|
|
|
+ reset();
|
|
|
+ parseFieldMatcher(indexSettings.getParseFieldMatcher());
|
|
|
+ try {
|
|
|
+ Query query = toQuery(queryBuilder, this);
|
|
|
+ return new ParsedQuery(query, copyNamedQueries());
|
|
|
+ } catch(QueryShardException | ParsingException e ) {
|
|
|
+ throw e;
|
|
|
+ } catch(Exception e) {
|
|
|
+ throw new QueryShardException(this, "failed to create query: {}", e, queryBuilder);
|
|
|
+ } finally {
|
|
|
+ this.reset();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Query toQuery(QueryBuilder<?> queryBuilder, QueryShardContext context) throws IOException {
|
|
|
+ Query query = queryBuilder.toQuery(context);
|
|
|
+ if (query == null) {
|
|
|
+ query = Queries.newMatchNoDocsQuery();
|
|
|
+ }
|
|
|
+ return query;
|
|
|
+ }
|
|
|
+
|
|
|
}
|