Merge branch 'master' into feature/query-refactoring
Conflicts: core/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java core/src/test/java/org/elasticsearch/index/query/guice/MyJsonQueryParser.java core/src/test/java/org/elasticsearch/index/query/plugin/PluginJsonQueryParser.java
This commit is contained in:
commit
7f673fbdfd
|
@ -109,7 +109,11 @@ public class PropertyPlaceholder {
|
|||
propVal = defaultValue;
|
||||
}
|
||||
if (propVal == null && placeholderResolver.shouldIgnoreMissing(placeholder)) {
|
||||
propVal = "";
|
||||
if (placeholderResolver.shouldRemoveMissingPlaceholder(placeholder)) {
|
||||
propVal = "";
|
||||
} else {
|
||||
return strVal;
|
||||
}
|
||||
}
|
||||
if (propVal != null) {
|
||||
// Recursive invocation, parsing placeholders contained in the
|
||||
|
@ -170,5 +174,13 @@ public class PropertyPlaceholder {
|
|||
String resolvePlaceholder(String placeholderName);
|
||||
|
||||
boolean shouldIgnoreMissing(String placeholderName);
|
||||
|
||||
/**
|
||||
* Allows for special handling for ignored missing placeholders that may be resolved elsewhere
|
||||
*
|
||||
* @param placeholderName the name of the placeholder to resolve.
|
||||
* @return true if the placeholder should be replaced with a empty string
|
||||
*/
|
||||
boolean shouldRemoveMissingPlaceholder(String placeholderName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1245,7 +1245,7 @@ public final class Settings implements ToXContent {
|
|||
* tries and resolve it against an environment variable ({@link System#getenv(String)}), and last, tries
|
||||
* and replace it with another setting already set on this builder.
|
||||
*/
|
||||
public Builder replacePropertyPlaceholders(String... ignoredValues) {
|
||||
public Builder replacePropertyPlaceholders() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new PropertyPlaceholder.PlaceholderResolver() {
|
||||
@Override
|
||||
|
@ -1268,26 +1268,22 @@ public final class Settings implements ToXContent {
|
|||
@Override
|
||||
public boolean shouldIgnoreMissing(String placeholderName) {
|
||||
// if its an explicit env var, we are ok with not having a value for it and treat it as optional
|
||||
if (placeholderName.startsWith("env.")) {
|
||||
if (placeholderName.startsWith("env.") || placeholderName.startsWith("prompt.")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRemoveMissingPlaceholder(String placeholderName) {
|
||||
if (placeholderName.startsWith("prompt.")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
for (Map.Entry<String, String> entry : Maps.newHashMap(map).entrySet()) {
|
||||
String possiblePlaceholder = entry.getValue();
|
||||
boolean ignored = false;
|
||||
for (String ignoredValue : ignoredValues) {
|
||||
if (ignoredValue.equals(possiblePlaceholder)) {
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = propertyPlaceholder.replacePlaceholders(possiblePlaceholder, placeholderResolver);
|
||||
String value = propertyPlaceholder.replacePlaceholders(entry.getValue(), placeholderResolver);
|
||||
// if the values exists and has length, we should maintain it in the map
|
||||
// otherwise, the replace process resolved into removing it
|
||||
if (Strings.hasLength(value)) {
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* 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 com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.Scopes;
|
||||
import org.elasticsearch.common.inject.assistedinject.FactoryProvider;
|
||||
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.query.support.InnerHitsQueryParserHelper;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexQueryParserModule extends AbstractModule {
|
||||
|
||||
/**
|
||||
* A custom processor that can be extended to process and bind custom implementations of
|
||||
* {@link QueryParserFactory}, and {@link FilterParser}.
|
||||
*/
|
||||
public static class QueryParsersProcessor {
|
||||
|
||||
/**
|
||||
* Extension point to bind a custom {@link QueryParserFactory}.
|
||||
*/
|
||||
public void processXContentQueryParsers(XContentQueryParsersBindings bindings) {
|
||||
|
||||
}
|
||||
|
||||
public static class XContentQueryParsersBindings {
|
||||
|
||||
private final MapBinder<String, QueryParserFactory> binder;
|
||||
private final Map<String, Settings> groupSettings;
|
||||
|
||||
public XContentQueryParsersBindings(MapBinder<String, QueryParserFactory> binder, Map<String, Settings> groupSettings) {
|
||||
this.binder = binder;
|
||||
this.groupSettings = groupSettings;
|
||||
}
|
||||
|
||||
public MapBinder<String, QueryParserFactory> binder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public Map<String, Settings> groupSettings() {
|
||||
return groupSettings;
|
||||
}
|
||||
|
||||
public void processXContentQueryParser(String name, Class<? extends QueryParser> xcontentQueryParser) {
|
||||
if (!groupSettings.containsKey(name)) {
|
||||
binder.addBinding(name).toProvider(FactoryProvider.newFactory(QueryParserFactory.class, xcontentQueryParser)).in(Scopes.SINGLETON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
private final LinkedList<QueryParsersProcessor> processors = Lists.newLinkedList();
|
||||
|
||||
private final Map<String, Class<? extends QueryParser>> queries = Maps.newHashMap();
|
||||
|
||||
public IndexQueryParserModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom query parser.
|
||||
*
|
||||
* @param name The name of the query parser
|
||||
* @param queryParser the class of the query parser
|
||||
*/
|
||||
public void addQueryParser(String name, Class<? extends QueryParser> queryParser) {
|
||||
queries.put(name, queryParser);
|
||||
}
|
||||
|
||||
public IndexQueryParserModule addProcessor(QueryParsersProcessor processor) {
|
||||
processors.addFirst(processor);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
bind(IndexQueryParserService.class).asEagerSingleton();
|
||||
bind(InnerHitsQueryParserHelper.class).asEagerSingleton();
|
||||
|
||||
// handle XContenQueryParsers
|
||||
MapBinder<String, QueryParserFactory> queryBinder
|
||||
= MapBinder.newMapBinder(binder(), String.class, QueryParserFactory.class);
|
||||
Map<String, Settings> xContentQueryParserGroups = settings.getGroups(IndexQueryParserService.Defaults.QUERY_PREFIX);
|
||||
for (Map.Entry<String, Settings> entry : xContentQueryParserGroups.entrySet()) {
|
||||
String qName = entry.getKey();
|
||||
Settings qSettings = entry.getValue();
|
||||
Class<? extends QueryParser> type = qSettings.getAsClass("type", null);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Query Parser [" + qName + "] must be provided with a type");
|
||||
}
|
||||
queryBinder.addBinding(qName).toProvider(FactoryProvider.newFactory(QueryParserFactory.class,
|
||||
qSettings.getAsClass("type", null))).in(Scopes.SINGLETON);
|
||||
}
|
||||
|
||||
QueryParsersProcessor.XContentQueryParsersBindings xContentQueryParsersBindings = new QueryParsersProcessor.XContentQueryParsersBindings(queryBinder, xContentQueryParserGroups);
|
||||
for (QueryParsersProcessor processor : processors) {
|
||||
processor.processXContentQueryParsers(xContentQueryParsersBindings);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Class<? extends QueryParser>> entry : queries.entrySet()) {
|
||||
queryBinder.addBinding(entry.getKey()).toProvider(FactoryProvider.newFactory(QueryParserFactory.class, entry.getValue())).in(Scopes.SINGLETON);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.CloseableThreadLocal;
|
||||
import org.elasticsearch.Version;
|
||||
|
@ -48,23 +46,12 @@ import org.elasticsearch.script.ScriptService;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexQueryParserService extends AbstractIndexComponent {
|
||||
|
||||
public static final class Defaults {
|
||||
public static final String QUERY_PREFIX = "index.queryparser.query";
|
||||
public static final String FILTER_PREFIX = "index.queryparser.filter";
|
||||
}
|
||||
|
||||
public static final String DEFAULT_FIELD = "index.query.default_field";
|
||||
public static final String QUERY_STRING_LENIENT = "index.query_string.lenient";
|
||||
public static final String PARSE_STRICT = "index.query.parse.strict";
|
||||
|
@ -91,7 +78,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
|
||||
final BitsetFilterCache bitsetFilterCache;
|
||||
|
||||
private final Map<String, QueryParser> queryParsers;
|
||||
private final IndicesQueriesRegistry indicesQueriesRegistry;
|
||||
|
||||
private String defaultField;
|
||||
private boolean queryStringLenient;
|
||||
|
@ -104,8 +91,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
ScriptService scriptService, AnalysisService analysisService,
|
||||
MapperService mapperService, IndexCache indexCache, IndexFieldDataService fieldDataService,
|
||||
BitsetFilterCache bitsetFilterCache,
|
||||
@Nullable SimilarityService similarityService,
|
||||
@Nullable Map<String, QueryParserFactory> namedQueryParsers) {
|
||||
@Nullable SimilarityService similarityService) {
|
||||
super(index, indexSettings);
|
||||
this.scriptService = scriptService;
|
||||
this.analysisService = analysisService;
|
||||
|
@ -119,29 +105,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
this.queryStringLenient = indexSettings.getAsBoolean(QUERY_STRING_LENIENT, false);
|
||||
this.strict = indexSettings.getAsBoolean(PARSE_STRICT, false);
|
||||
this.defaultAllowUnmappedFields = indexSettings.getAsBoolean(ALLOW_UNMAPPED, true);
|
||||
|
||||
List<QueryParser> queryParsers = newArrayList();
|
||||
if (namedQueryParsers != null) {
|
||||
Map<String, Settings> queryParserGroups = indexSettings.getGroups(IndexQueryParserService.Defaults.QUERY_PREFIX);
|
||||
for (Map.Entry<String, QueryParserFactory> entry : namedQueryParsers.entrySet()) {
|
||||
String queryParserName = entry.getKey();
|
||||
QueryParserFactory queryParserFactory = entry.getValue();
|
||||
Settings queryParserSettings = queryParserGroups.get(queryParserName);
|
||||
if (queryParserSettings == null) {
|
||||
queryParserSettings = EMPTY_SETTINGS;
|
||||
}
|
||||
queryParsers.add(queryParserFactory.create(queryParserName, queryParserSettings));
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, QueryParser> queryParsersMap = newHashMap();
|
||||
queryParsersMap.putAll(indicesQueriesRegistry.queryParsers());
|
||||
if (queryParsers != null) {
|
||||
for (QueryParser queryParser : queryParsers) {
|
||||
add(queryParsersMap, queryParser);
|
||||
}
|
||||
}
|
||||
this.queryParsers = ImmutableMap.copyOf(queryParsersMap);
|
||||
this.indicesQueriesRegistry = indicesQueriesRegistry;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
@ -157,7 +121,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
}
|
||||
|
||||
public QueryParser queryParser(String name) {
|
||||
return queryParsers.get(name);
|
||||
return indicesQueriesRegistry.queryParsers().get(name);
|
||||
}
|
||||
|
||||
public ParsedQuery parse(QueryBuilder queryBuilder) {
|
||||
|
@ -349,10 +313,4 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
parseContext.reset(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void add(Map<String, QueryParser> map, QueryParser queryParser) {
|
||||
for (String name : queryParser.names()) {
|
||||
map.put(name.intern(), queryParser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* 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.common.settings.Settings;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface QueryParserFactory {
|
||||
|
||||
QueryParser create(String name, Settings settings);
|
||||
}
|
|
@ -57,7 +57,6 @@ import org.elasticsearch.index.indexing.IndexingStats;
|
|||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.mapper.MapperServiceModule;
|
||||
import org.elasticsearch.index.merge.MergeStats;
|
||||
import org.elasticsearch.index.query.IndexQueryParserModule;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.index.recovery.RecoveryStats;
|
||||
import org.elasticsearch.index.refresh.RefreshStats;
|
||||
|
@ -315,7 +314,6 @@ public class IndicesService extends AbstractLifecycleComponent<IndicesService> i
|
|||
modules.add(new IndexCacheModule(indexSettings));
|
||||
modules.add(new IndexFieldDataModule(indexSettings));
|
||||
modules.add(new MapperServiceModule());
|
||||
modules.add(new IndexQueryParserModule(indexSettings));
|
||||
modules.add(new IndexAliasesServiceModule());
|
||||
modules.add(new IndexModule(indexSettings));
|
||||
|
||||
|
|
|
@ -30,30 +30,21 @@ import java.util.Set;
|
|||
|
||||
public class IndicesQueriesModule extends AbstractModule {
|
||||
|
||||
private Set<Class<QueryParser>> queryParsersClasses = Sets.newHashSet();
|
||||
private Set<QueryParser> queryParsers = Sets.newHashSet();
|
||||
private Set<Class<? extends QueryParser>> queryParsersClasses = Sets.newHashSet();
|
||||
|
||||
public synchronized IndicesQueriesModule addQuery(Class<QueryParser> queryParser) {
|
||||
public synchronized IndicesQueriesModule addQuery(Class<? extends QueryParser> queryParser) {
|
||||
queryParsersClasses.add(queryParser);
|
||||
return this;
|
||||
}
|
||||
|
||||
public synchronized IndicesQueriesModule addQuery(QueryParser queryParser) {
|
||||
queryParsers.add(queryParser);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(IndicesQueriesRegistry.class).asEagerSingleton();
|
||||
|
||||
Multibinder<QueryParser> qpBinders = Multibinder.newSetBinder(binder(), QueryParser.class);
|
||||
for (Class<QueryParser> queryParser : queryParsersClasses) {
|
||||
for (Class<? extends QueryParser> queryParser : queryParsersClasses) {
|
||||
qpBinders.addBinding().to(queryParser).asEagerSingleton();
|
||||
}
|
||||
for (QueryParser queryParser : queryParsers) {
|
||||
qpBinders.addBinding().toInstance(queryParser);
|
||||
}
|
||||
qpBinders.addBinding().to(MatchQueryParser.class).asEagerSingleton();
|
||||
qpBinders.addBinding().to(MultiMatchQueryParser.class).asEagerSingleton();
|
||||
qpBinders.addBinding().to(NestedQueryParser.class).asEagerSingleton();
|
||||
|
|
|
@ -30,9 +30,6 @@ import org.elasticsearch.index.query.QueryParser;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndicesQueriesRegistry extends AbstractComponent {
|
||||
|
||||
private ImmutableMap<String, QueryParser> queryParsers;
|
||||
|
@ -42,27 +39,17 @@ public class IndicesQueriesRegistry extends AbstractComponent {
|
|||
super(settings);
|
||||
Map<String, QueryParser> queryParsers = Maps.newHashMap();
|
||||
for (QueryParser queryParser : injectedQueryParsers) {
|
||||
addQueryParser(queryParsers, queryParser);
|
||||
for (String name : queryParser.names()) {
|
||||
queryParsers.put(name, queryParser);
|
||||
}
|
||||
}
|
||||
this.queryParsers = ImmutableMap.copyOf(queryParsers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a global query parser.
|
||||
* Returns all the registered query parsers
|
||||
*/
|
||||
public synchronized void addQueryParser(QueryParser queryParser) {
|
||||
Map<String, QueryParser> queryParsers = Maps.newHashMap(this.queryParsers);
|
||||
addQueryParser(queryParsers, queryParser);
|
||||
this.queryParsers = ImmutableMap.copyOf(queryParsers);
|
||||
}
|
||||
|
||||
public ImmutableMap<String, QueryParser> queryParsers() {
|
||||
return queryParsers;
|
||||
}
|
||||
|
||||
private void addQueryParser(Map<String, QueryParser> queryParsers, QueryParser queryParser) {
|
||||
for (String name : queryParser.names()) {
|
||||
queryParsers.put(name, queryParser);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,8 +44,8 @@ public class InternalSettingsPreparer {
|
|||
|
||||
static final List<String> ALLOWED_SUFFIXES = ImmutableList.of(".yml", ".yaml", ".json", ".properties");
|
||||
|
||||
public static final String SECRET_PROMPT_VALUE = "${prompt::secret}";
|
||||
public static final String TEXT_PROMPT_VALUE = "${prompt::text}";
|
||||
public static final String SECRET_PROMPT_VALUE = "${prompt.secret}";
|
||||
public static final String TEXT_PROMPT_VALUE = "${prompt.text}";
|
||||
public static final String IGNORE_SYSTEM_PROPERTIES_SETTING = "config.ignore_system_properties";
|
||||
|
||||
/**
|
||||
|
@ -72,9 +72,6 @@ public class InternalSettingsPreparer {
|
|||
public static Tuple<Settings, Environment> prepareSettings(Settings pSettings, boolean loadConfigSettings, Terminal terminal) {
|
||||
// ignore this prefixes when getting properties from es. and elasticsearch.
|
||||
String[] ignorePrefixes = new String[]{"es.default.", "elasticsearch.default."};
|
||||
// ignore the special prompt placeholders since they have the same format as property placeholders and will be resolved
|
||||
// as having a default value because of the ':' in the format
|
||||
String[] ignoredPlaceholders = new String[] { SECRET_PROMPT_VALUE, TEXT_PROMPT_VALUE };
|
||||
boolean useSystemProperties = !pSettings.getAsBoolean(IGNORE_SYSTEM_PROPERTIES_SETTING, false);
|
||||
// just create enough settings to build the environment
|
||||
Settings.Builder settingsBuilder = settingsBuilder().put(pSettings);
|
||||
|
@ -84,7 +81,7 @@ public class InternalSettingsPreparer {
|
|||
.putProperties("elasticsearch.", System.getProperties(), ignorePrefixes)
|
||||
.putProperties("es.", System.getProperties(), ignorePrefixes);
|
||||
}
|
||||
settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders);
|
||||
settingsBuilder.replacePropertyPlaceholders();
|
||||
|
||||
Environment environment = new Environment(settingsBuilder.build());
|
||||
|
||||
|
@ -122,7 +119,7 @@ public class InternalSettingsPreparer {
|
|||
settingsBuilder.putProperties("elasticsearch.", System.getProperties(), ignorePrefixes)
|
||||
.putProperties("es.", System.getProperties(), ignorePrefixes);
|
||||
}
|
||||
settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders);
|
||||
settingsBuilder.replacePropertyPlaceholders();
|
||||
|
||||
// allow to force set properties based on configuration of the settings provided
|
||||
for (Map.Entry<String, String> entry : pSettings.getAsMap().entrySet()) {
|
||||
|
@ -132,7 +129,7 @@ public class InternalSettingsPreparer {
|
|||
settingsBuilder.put(setting.substring("force.".length()), entry.getValue());
|
||||
}
|
||||
}
|
||||
settingsBuilder.replacePropertyPlaceholders(ignoredPlaceholders);
|
||||
settingsBuilder.replacePropertyPlaceholders();
|
||||
|
||||
// generate the name
|
||||
if (settingsBuilder.get("name") == null) {
|
||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.search;
|
|||
import com.carrotsearch.hppc.ObjectHashSet;
|
||||
import com.carrotsearch.hppc.ObjectSet;
|
||||
import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
|
@ -682,9 +681,10 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
|
||||
private void parseTemplate(ShardSearchRequest request) {
|
||||
|
||||
final ExecutableScript executable;
|
||||
BytesReference processedQuery;
|
||||
if (request.template() != null) {
|
||||
executable = this.scriptService.executable(request.template(), ScriptContext.Standard.SEARCH);
|
||||
ExecutableScript executable = this.scriptService.executable(request.template(), ScriptContext.Standard.SEARCH);
|
||||
processedQuery = (BytesReference) executable.run();
|
||||
} else {
|
||||
if (!hasLength(request.templateSource())) {
|
||||
return;
|
||||
|
@ -700,13 +700,16 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
//Try to double parse for nested template id/file
|
||||
parser = null;
|
||||
try {
|
||||
byte[] templateBytes = template.getScript().getBytes(Charsets.UTF_8);
|
||||
parser = XContentFactory.xContent(templateBytes).createParser(templateBytes);
|
||||
ExecutableScript executable = this.scriptService.executable(template, ScriptContext.Standard.SEARCH);
|
||||
processedQuery = (BytesReference) executable.run();
|
||||
parser = XContentFactory.xContent(processedQuery).createParser(processedQuery);
|
||||
} catch (ElasticsearchParseException epe) {
|
||||
//This was an non-nested template, the parse failure was due to this, it is safe to assume this refers to a file
|
||||
//for backwards compatibility and keep going
|
||||
template = new Template(template.getScript(), ScriptService.ScriptType.FILE, MustacheScriptEngineService.NAME,
|
||||
null, template.getParams());
|
||||
ExecutableScript executable = this.scriptService.executable(template, ScriptContext.Standard.SEARCH);
|
||||
processedQuery = (BytesReference) executable.run();
|
||||
}
|
||||
if (parser != null) {
|
||||
try {
|
||||
|
@ -715,11 +718,16 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
//An inner template referring to a filename or id
|
||||
template = new Template(innerTemplate.getScript(), innerTemplate.getType(),
|
||||
MustacheScriptEngineService.NAME, null, template.getParams());
|
||||
ExecutableScript executable = this.scriptService.executable(template, ScriptContext.Standard.SEARCH);
|
||||
processedQuery = (BytesReference) executable.run();
|
||||
}
|
||||
} catch (ScriptParseException e) {
|
||||
// No inner template found, use original template from above
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ExecutableScript executable = this.scriptService.executable(template, ScriptContext.Standard.SEARCH);
|
||||
processedQuery = (BytesReference) executable.run();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchParseException("Failed to parse template", e);
|
||||
|
@ -730,10 +738,7 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
if (!hasLength(template.getScript())) {
|
||||
throw new ElasticsearchParseException("Template must have [template] field configured");
|
||||
}
|
||||
executable = this.scriptService.executable(template, ScriptContext.Standard.SEARCH);
|
||||
}
|
||||
|
||||
BytesReference processedQuery = (BytesReference) executable.run();
|
||||
request.source(processedQuery);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("foo1", "bar1");
|
||||
map.put("foo2", "bar2");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("bar1", propertyPlaceholder.replacePlaceholders("{foo1}", placeholderResolver));
|
||||
assertEquals("a bar1b", propertyPlaceholder.replacePlaceholders("a {foo1}b", placeholderResolver));
|
||||
assertEquals("bar1bar2", propertyPlaceholder.replacePlaceholders("{foo1}{foo2}", placeholderResolver));
|
||||
|
@ -48,7 +48,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
PropertyPlaceholder ppShorterPrefix = new PropertyPlaceholder("{", "}}", false);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("foo", "bar");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("bar", ppEqualsPrefix.replacePlaceholders("{foo}", placeholderResolver));
|
||||
assertEquals("bar", ppLongerPrefix.replacePlaceholders("${foo}", placeholderResolver));
|
||||
assertEquals("bar", ppShorterPrefix.replacePlaceholders("{foo}}", placeholderResolver));
|
||||
|
@ -58,7 +58,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
public void testDefaultValue() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("bar", propertyPlaceholder.replacePlaceholders("${foo:bar}", placeholderResolver));
|
||||
assertEquals("", propertyPlaceholder.replacePlaceholders("${foo:}", placeholderResolver));
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
public void testIgnoredUnresolvedPlaceholder() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", true);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("${foo}", propertyPlaceholder.replacePlaceholders("${foo}", placeholderResolver));
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
public void testNotIgnoredUnresolvedPlaceholder() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
propertyPlaceholder.replacePlaceholders("${foo}", placeholderResolver);
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
public void testShouldIgnoreMissing() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, true);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, true, true);
|
||||
assertEquals("bar", propertyPlaceholder.replacePlaceholders("bar${foo}", placeholderResolver));
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
map.put("foo", "${foo1}");
|
||||
map.put("foo1", "${foo2}");
|
||||
map.put("foo2", "bar");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("bar", propertyPlaceholder.replacePlaceholders("${foo}", placeholderResolver));
|
||||
assertEquals("abarb", propertyPlaceholder.replacePlaceholders("a${foo}b", placeholderResolver));
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
map.put("foo1", "${foo2}");
|
||||
map.put("foo2", "bar");
|
||||
map.put("barbar", "baz");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("baz", propertyPlaceholder.replacePlaceholders("${bar${foo}}", placeholderResolver));
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
map.put("foo1", "{foo2}");
|
||||
map.put("foo2", "bar");
|
||||
map.put("barbar", "baz");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("baz", propertyPlaceholder.replacePlaceholders("{bar{foo}}", placeholderResolver));
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
map.put("foo1", "{foo2}}");
|
||||
map.put("foo2", "bar");
|
||||
map.put("barbar", "baz");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
assertEquals("baz", propertyPlaceholder.replacePlaceholders("{bar{foo}}}}", placeholderResolver));
|
||||
}
|
||||
|
||||
|
@ -141,17 +141,27 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("foo", "${bar}");
|
||||
map.put("bar", "${foo}");
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false);
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, false, true);
|
||||
propertyPlaceholder.replacePlaceholders("${foo}", placeholderResolver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldRemoveMissing() {
|
||||
PropertyPlaceholder propertyPlaceholder = new PropertyPlaceholder("${", "}", false);
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
PropertyPlaceholder.PlaceholderResolver placeholderResolver = new SimplePlaceholderResolver(map, true, false);
|
||||
assertEquals("bar${foo}", propertyPlaceholder.replacePlaceholders("bar${foo}", placeholderResolver));
|
||||
}
|
||||
|
||||
private class SimplePlaceholderResolver implements PropertyPlaceholder.PlaceholderResolver {
|
||||
private Map<String, String> map;
|
||||
private boolean shouldIgnoreMissing;
|
||||
private boolean shouldRemoveMissing;
|
||||
|
||||
SimplePlaceholderResolver(Map<String, String> map, boolean shouldIgnoreMissing) {
|
||||
SimplePlaceholderResolver(Map<String, String> map, boolean shouldIgnoreMissing, boolean shouldRemoveMissing) {
|
||||
this.map = map;
|
||||
this.shouldIgnoreMissing = shouldIgnoreMissing;
|
||||
this.shouldRemoveMissing = shouldRemoveMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -163,5 +173,10 @@ public class PropertyPlaceholderTest extends ElasticsearchTestCase {
|
|||
public boolean shouldIgnoreMissing(String placeholderName) {
|
||||
return shouldIgnoreMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRemoveMissingPlaceholder(String placeholderName) {
|
||||
return shouldRemoveMissing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,14 +138,14 @@ public class SettingsTests extends ElasticsearchTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReplacePropertiesPlaceholderIgnores() {
|
||||
public void testReplacePropertiesPlaceholderIgnoresPrompt() {
|
||||
Settings settings = settingsBuilder()
|
||||
.put("setting1", "${foo.bar}")
|
||||
.put("setting2", "${foo.bar1}")
|
||||
.replacePropertyPlaceholders("${foo.bar}", "${foo.bar1}")
|
||||
.put("setting1", "${prompt.text}")
|
||||
.put("setting2", "${prompt.secret}")
|
||||
.replacePropertyPlaceholders()
|
||||
.build();
|
||||
assertThat(settings.get("setting1"), is("${foo.bar}"));
|
||||
assertThat(settings.get("setting2"), is("${foo.bar1}"));
|
||||
assertThat(settings.get("setting1"), is("${prompt.text}"));
|
||||
assertThat(settings.get("setting2"), is("${prompt.secret}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -113,7 +113,6 @@ public abstract class BaseQueryTestCase<QB extends QueryBuilder<QB>> extends Ela
|
|||
new AnalysisModule(settings),
|
||||
new SimilarityModule(settings),
|
||||
new IndexNameModule(index),
|
||||
new IndexQueryParserModule(settings),
|
||||
new FunctionScoreModule(),
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
|
|
|
@ -41,7 +41,6 @@ import org.elasticsearch.action.termvectors.*;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.MoreLikeThisQuery;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.lucene.search.function.BoostScoreFunction;
|
||||
|
@ -50,12 +49,9 @@ import org.elasticsearch.common.lucene.search.function.WeightFactorFunction;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.DistanceUnit;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexService;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||
|
@ -71,7 +67,6 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -83,86 +78,13 @@ import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.
|
|||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBooleanSubQuery;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
||||
|
||||
private IndexQueryParserService queryParser;
|
||||
|
||||
private static class DummyQuery extends Query {
|
||||
|
||||
public boolean isFilter;
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DummyQueryParser extends AbstractIndexComponent implements QueryParser {
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
public DummyQueryParser(Index index, Settings indexSettings) {
|
||||
super(index, indexSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] names() {
|
||||
return new String[] {DummyQueryBuilder.NAME};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
return fromXContent(parseContext).toQuery(parseContext);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
assertEquals(XContentParser.Token.END_OBJECT, parseContext.parser().nextToken());
|
||||
return new DummyQueryBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DummyQueryBuilder getBuilderPrototype() {
|
||||
return new DummyQueryBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummyQueryBuilder extends QueryBuilder {
|
||||
|
||||
public static final String NAME = "dummy";
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject("dummy").endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query toQuery(QueryParseContext parseContext) throws QueryParsingException, IOException {
|
||||
DummyQuery query = new DummyQuery();
|
||||
query.isFilter = parseContext.isFilter();
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String queryId() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
private static DummyQueryBuilder dummyQuery() {
|
||||
return new DummyQueryBuilder();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
Settings settings = Settings.settingsBuilder()
|
||||
.put("index.queryparser.query.dummy.type", DummyQueryParser.class)
|
||||
.put("index.cache.filter.type", "none")
|
||||
.put("name", "SimpleIndexQueryParserTests")
|
||||
.build();
|
||||
|
@ -1088,7 +1010,6 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
|||
assertThat(clauses[3].getOccur(), equalTo(BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBoolQuery() throws IOException {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
|
@ -1989,7 +1910,6 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
|||
assertThat(filter.bottomRight().lon(), closeTo(-80, 0.00001));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGeoBoundingBoxFilter1() throws IOException {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
|
@ -2489,72 +2409,11 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
|||
public void testTermsQueryFilter() throws Exception {
|
||||
// TermsQuery is tricky in that it parses differently as a query or a filter
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
Query q = queryParser.parse(termsQuery("foo", Arrays.asList("bar"))).query();
|
||||
Query q = queryParser.parse(termsQuery("foo", "bar")).query();
|
||||
assertThat(q, instanceOf(BooleanQuery.class));
|
||||
|
||||
ConstantScoreQuery csq = (ConstantScoreQuery) queryParser.parse(constantScoreQuery(termsQuery("foo", Arrays.asList("bar")))).query();
|
||||
ConstantScoreQuery csq = (ConstantScoreQuery) queryParser.parse(constantScoreQuery(termsQuery("foo", "bar"))).query();
|
||||
q = csq.getQuery();
|
||||
assertThat(q, instanceOf(TermsQuery.class));
|
||||
}
|
||||
|
||||
public void testConstantScoreParsesFilter() throws Exception {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
Query q = queryParser.parse(constantScoreQuery(dummyQuery())).query();
|
||||
Query inner = ((ConstantScoreQuery) q).getQuery();
|
||||
assertThat(inner, instanceOf(DummyQuery.class));
|
||||
assertEquals(true, ((DummyQuery) inner).isFilter);
|
||||
}
|
||||
|
||||
public void testBooleanParsesFilter() throws Exception {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
// single clause, serialized as inner object
|
||||
Query q = queryParser.parse(boolQuery()
|
||||
.should(dummyQuery())
|
||||
.must(dummyQuery())
|
||||
.filter(dummyQuery())
|
||||
.mustNot(dummyQuery())).query();
|
||||
assertThat(q, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bq = (BooleanQuery) q;
|
||||
assertEquals(4, bq.clauses().size());
|
||||
for (BooleanClause clause : bq.clauses()) {
|
||||
DummyQuery dummy = (DummyQuery) clause.getQuery();
|
||||
switch (clause.getOccur()) {
|
||||
case FILTER:
|
||||
case MUST_NOT:
|
||||
assertEquals(true, dummy.isFilter);
|
||||
break;
|
||||
case MUST:
|
||||
case SHOULD:
|
||||
assertEquals(false, dummy.isFilter);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
// multiple clauses, serialized as inner arrays
|
||||
q = queryParser.parse(boolQuery()
|
||||
.should(dummyQuery()).should(dummyQuery())
|
||||
.must(dummyQuery()).must(dummyQuery())
|
||||
.filter(dummyQuery()).filter(dummyQuery())
|
||||
.mustNot(dummyQuery()).mustNot(dummyQuery())).query();
|
||||
assertThat(q, instanceOf(BooleanQuery.class));
|
||||
bq = (BooleanQuery) q;
|
||||
assertEquals(8, bq.clauses().size());
|
||||
for (BooleanClause clause : bq.clauses()) {
|
||||
DummyQuery dummy = (DummyQuery) clause.getQuery();
|
||||
switch (clause.getOccur()) {
|
||||
case FILTER:
|
||||
case MUST_NOT:
|
||||
assertEquals(true, dummy.isFilter);
|
||||
break;
|
||||
case MUST:
|
||||
case SHOULD:
|
||||
assertEquals(false, dummy.isFilter);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@ public class TemplateQueryParserTest extends ElasticsearchTestCase {
|
|||
new AnalysisModule(settings),
|
||||
new SimilarityModule(settings),
|
||||
new IndexNameModule(index),
|
||||
new IndexQueryParserModule(settings),
|
||||
new FunctionScoreModule(),
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
|
@ -118,6 +117,35 @@ public class TemplateQueryParserTest extends ElasticsearchTestCase {
|
|||
assertTrue("Parsing template query failed.", query instanceof MatchAllDocsQuery);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseTemplateAsSingleStringWithConditionalClause() throws IOException {
|
||||
String templateString = "{" + " \"inline\" : \"{ \\\"match_{{#use_it}}{{template}}{{/use_it}}\\\":{} }\"," + " \"params\":{"
|
||||
+ " \"template\":\"all\"," + " \"use_it\": true" + " }" + "}";
|
||||
XContentParser templateSourceParser = XContentFactory.xContent(templateString).createParser(templateString);
|
||||
context.reset(templateSourceParser);
|
||||
|
||||
TemplateQueryParser parser = injector.getInstance(TemplateQueryParser.class);
|
||||
Query query = parser.parse(context);
|
||||
assertTrue("Parsing template query failed.", query instanceof MatchAllDocsQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the template query parser can parse and evaluate template
|
||||
* expressed as a single string but still it expects only the query
|
||||
* specification (thus this test should fail with specific exception).
|
||||
*/
|
||||
@Test(expected = QueryParsingException.class)
|
||||
public void testParseTemplateFailsToParseCompleteQueryAsSingleString() throws IOException {
|
||||
String templateString = "{" + " \"inline\" : \"{ \\\"size\\\": \\\"{{size}}\\\", \\\"query\\\":{\\\"match_all\\\":{}}}\","
|
||||
+ " \"params\":{" + " \"size\":2" + " }\n" + "}";
|
||||
|
||||
XContentParser templateSourceParser = XContentFactory.xContent(templateString).createParser(templateString);
|
||||
context.reset(templateSourceParser);
|
||||
|
||||
TemplateQueryParser parser = injector.getInstance(TemplateQueryParser.class);
|
||||
parser.parse(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParserCanExtractTemplateNames() throws Exception {
|
||||
String templateString = "{ \"file\": \"storedTemplate\" ,\"params\":{\"template\":\"all\" } } ";
|
||||
|
|
|
@ -232,6 +232,67 @@ public class TemplateQueryTest extends ElasticsearchIntegrationTest {
|
|||
assertHitCount(searchResponse, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchTemplateQueryFromFile() throws Exception {
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.indices("_all");
|
||||
String templateString = "{" + " \"file\": \"full-query-template\"," + " \"params\":{" + " \"mySize\": 2,"
|
||||
+ " \"myField\": \"text\"," + " \"myValue\": \"value1\"" + " }" + "}";
|
||||
BytesReference bytesRef = new BytesArray(templateString);
|
||||
searchRequest.templateSource(bytesRef);
|
||||
SearchResponse searchResponse = client().search(searchRequest).get();
|
||||
assertThat(searchResponse.getHits().hits().length, equalTo(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that template can be expressed as a single escaped string.
|
||||
*/
|
||||
@Test
|
||||
public void testTemplateQueryAsEscapedString() throws Exception {
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.indices("_all");
|
||||
String templateString = "{" + " \"template\" : \"{ \\\"size\\\": \\\"{{size}}\\\", \\\"query\\\":{\\\"match_all\\\":{}}}\","
|
||||
+ " \"params\":{" + " \"size\": 1" + " }" + "}";
|
||||
BytesReference bytesRef = new BytesArray(templateString);
|
||||
searchRequest.templateSource(bytesRef);
|
||||
SearchResponse searchResponse = client().search(searchRequest).get();
|
||||
assertThat(searchResponse.getHits().hits().length, equalTo(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that template can contain conditional clause. In this case it is at
|
||||
* the beginning of the string.
|
||||
*/
|
||||
@Test
|
||||
public void testTemplateQueryAsEscapedStringStartingWithConditionalClause() throws Exception {
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.indices("_all");
|
||||
String templateString = "{"
|
||||
+ " \"template\" : \"{ {{#use_size}} \\\"size\\\": \\\"{{size}}\\\", {{/use_size}} \\\"query\\\":{\\\"match_all\\\":{}}}\","
|
||||
+ " \"params\":{" + " \"size\": 1," + " \"use_size\": true" + " }" + "}";
|
||||
BytesReference bytesRef = new BytesArray(templateString);
|
||||
searchRequest.templateSource(bytesRef);
|
||||
SearchResponse searchResponse = client().search(searchRequest).get();
|
||||
assertThat(searchResponse.getHits().hits().length, equalTo(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that template can contain conditional clause. In this case it is at
|
||||
* the end of the string.
|
||||
*/
|
||||
@Test
|
||||
public void testTemplateQueryAsEscapedStringWithConditionalClauseAtEnd() throws Exception {
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.indices("_all");
|
||||
String templateString = "{"
|
||||
+ " \"inline\" : \"{ \\\"query\\\":{\\\"match_all\\\":{}} {{#use_size}}, \\\"size\\\": \\\"{{size}}\\\" {{/use_size}} }\","
|
||||
+ " \"params\":{" + " \"size\": 1," + " \"use_size\": true" + " }" + "}";
|
||||
BytesReference bytesRef = new BytesArray(templateString);
|
||||
searchRequest.templateSource(bytesRef);
|
||||
SearchResponse searchResponse = client().search(searchRequest).get();
|
||||
assertThat(searchResponse.getHits().hits().length, equalTo(1));
|
||||
}
|
||||
|
||||
@Test(expected = SearchPhaseExecutionException.class)
|
||||
public void testIndexedTemplateClient() throws Exception {
|
||||
createIndex(ScriptService.SCRIPT_INDEX);
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* 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.guice;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexQueryParserModuleTests extends ElasticsearchSingleNodeTest {
|
||||
|
||||
@Test
|
||||
public void testCustomInjection() {
|
||||
Settings settings = settingsBuilder()
|
||||
.put("index.queryparser.query.my.type", MyJsonQueryParser.class)
|
||||
.put("index.queryparser.query.my.param1", "value1")
|
||||
.put("index.cache.filter.type", "none")
|
||||
.put("name", "IndexQueryParserModuleTests")
|
||||
.build();
|
||||
|
||||
IndexQueryParserService indexQueryParserService = createIndex("test", settings).queryParserService();
|
||||
|
||||
MyJsonQueryParser myJsonQueryParser = (MyJsonQueryParser) indexQueryParserService.queryParser("my");
|
||||
|
||||
assertThat(myJsonQueryParser.names()[0], equalTo("my"));
|
||||
assertThat(myJsonQueryParser.settings().get("param1"), equalTo("value1"));
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* 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.guice;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.assistedinject.Assisted;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.index.query.QueryWrappingQueryBuilder;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MyJsonQueryParser extends AbstractIndexComponent implements QueryParser {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
@Inject
|
||||
public MyJsonQueryParser(Index index, @IndexSettings Settings indexSettings, @Assisted String name, @Assisted Settings settings) {
|
||||
super(index, indexSettings);
|
||||
this.name = name;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] names() {
|
||||
return new String[]{this.name};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Settings settings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
Query query = parse(parseContext);
|
||||
return new QueryWrappingQueryBuilder(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder getBuilderPrototype() {
|
||||
throw new UnsupportedOperationException("Not implemented in test class");
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.inject.ModulesBuilder;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.env.EnvironmentModule;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexNameModule;
|
||||
import org.elasticsearch.index.analysis.AnalysisModule;
|
||||
import org.elasticsearch.index.cache.IndexCacheModule;
|
||||
import org.elasticsearch.index.query.IndexQueryParserModule;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreModule;
|
||||
import org.elasticsearch.index.settings.IndexSettingsModule;
|
||||
import org.elasticsearch.index.similarity.SimilarityModule;
|
||||
import org.elasticsearch.indices.breaker.CircuitBreakerService;
|
||||
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesModule;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPoolModule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexQueryParserPlugin2Tests extends ElasticsearchTestCase {
|
||||
|
||||
@Test
|
||||
public void testCustomInjection() throws InterruptedException {
|
||||
Settings settings = Settings.builder()
|
||||
.put("name", "testCustomInjection")
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
||||
.put("path.home", createTempDir()).build();
|
||||
|
||||
IndexQueryParserModule queryParserModule = new IndexQueryParserModule(settings);
|
||||
queryParserModule.addQueryParser("my", PluginJsonQueryParser.class);
|
||||
|
||||
Index index = new Index("test");
|
||||
Injector injector = new ModulesBuilder().add(
|
||||
new EnvironmentModule(new Environment(settings)),
|
||||
new SettingsModule(settings),
|
||||
new ThreadPoolModule(new ThreadPool(settings)),
|
||||
new IndicesQueriesModule(),
|
||||
new ScriptModule(settings),
|
||||
new IndexSettingsModule(index, settings),
|
||||
new IndexCacheModule(settings),
|
||||
new AnalysisModule(settings),
|
||||
new SimilarityModule(settings),
|
||||
queryParserModule,
|
||||
new IndexNameModule(index),
|
||||
new FunctionScoreModule(),
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ClusterService.class).toProvider(Providers.of((ClusterService) null));
|
||||
bind(CircuitBreakerService.class).to(NoneCircuitBreakerService.class);
|
||||
}
|
||||
}
|
||||
).createInjector();
|
||||
|
||||
IndexQueryParserService indexQueryParserService = injector.getInstance(IndexQueryParserService.class);
|
||||
|
||||
PluginJsonQueryParser myJsonQueryParser = (PluginJsonQueryParser) indexQueryParserService.queryParser("my");
|
||||
|
||||
assertThat(myJsonQueryParser.names()[0], equalTo("my"));
|
||||
|
||||
terminate(injector.getInstance(ThreadPool.class));
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.inject.ModulesBuilder;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.env.EnvironmentModule;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexNameModule;
|
||||
import org.elasticsearch.index.analysis.AnalysisModule;
|
||||
import org.elasticsearch.index.cache.IndexCacheModule;
|
||||
import org.elasticsearch.index.query.IndexQueryParserModule;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreModule;
|
||||
import org.elasticsearch.index.settings.IndexSettingsModule;
|
||||
import org.elasticsearch.index.similarity.SimilarityModule;
|
||||
import org.elasticsearch.indices.breaker.CircuitBreakerService;
|
||||
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesModule;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPoolModule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexQueryParserPluginTests extends ElasticsearchTestCase {
|
||||
|
||||
@Test
|
||||
public void testCustomInjection() throws InterruptedException {
|
||||
Settings settings = Settings.builder()
|
||||
.put("name", "testCustomInjection")
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
||||
.put("path.home", createTempDir()).build();
|
||||
|
||||
IndexQueryParserModule queryParserModule = new IndexQueryParserModule(settings);
|
||||
queryParserModule.addProcessor(new IndexQueryParserModule.QueryParsersProcessor() {
|
||||
@Override
|
||||
public void processXContentQueryParsers(XContentQueryParsersBindings bindings) {
|
||||
bindings.processXContentQueryParser("my", PluginJsonQueryParser.class);
|
||||
}
|
||||
});
|
||||
|
||||
Index index = new Index("test");
|
||||
Injector injector = new ModulesBuilder().add(
|
||||
new EnvironmentModule(new Environment(settings)),
|
||||
new SettingsModule(settings),
|
||||
new ThreadPoolModule(new ThreadPool(settings)),
|
||||
new IndicesQueriesModule(),
|
||||
new ScriptModule(settings),
|
||||
new IndexSettingsModule(index, settings),
|
||||
new IndexCacheModule(settings),
|
||||
new AnalysisModule(settings),
|
||||
new SimilarityModule(settings),
|
||||
queryParserModule,
|
||||
new IndexNameModule(index),
|
||||
new FunctionScoreModule(),
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ClusterService.class).toProvider(Providers.of((ClusterService) null));
|
||||
bind(CircuitBreakerService.class).to(NoneCircuitBreakerService.class);
|
||||
}
|
||||
}
|
||||
).createInjector();
|
||||
|
||||
IndexQueryParserService indexQueryParserService = injector.getInstance(IndexQueryParserService.class);
|
||||
|
||||
PluginJsonQueryParser myJsonQueryParser = (PluginJsonQueryParser) indexQueryParserService.queryParser("my");
|
||||
|
||||
assertThat(myJsonQueryParser.names()[0], equalTo("my"));
|
||||
|
||||
terminate(injector.getInstance(ThreadPool.class));
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.assistedinject.Assisted;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.index.query.QueryWrappingQueryBuilder;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class PluginJsonQueryParser extends AbstractIndexComponent implements QueryParser {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
@Inject
|
||||
public PluginJsonQueryParser(Index index, @IndexSettings Settings indexSettings, @Assisted String name, @Assisted Settings settings) {
|
||||
super(index, indexSettings);
|
||||
this.name = name;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] names() {
|
||||
return new String[]{this.name};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Settings settings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
Query query = parse(parseContext);
|
||||
return new QueryWrappingQueryBuilder(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder getBuilderPrototype() {
|
||||
throw new UnsupportedOperationException("Not implemented in test class");
|
||||
}
|
||||
}
|
|
@ -490,6 +490,10 @@ ignored. Instead filters are always used as their own cache key and elasticsearc
|
|||
makes decisions by itself about whether it should cache filters based on how
|
||||
often they are used.
|
||||
|
||||
Java plugins that register custom queries can do so by using the
|
||||
`IndicesQueriesModule#addQuery(Class<? extends QueryParser>)` method. Other
|
||||
ways to register custom queries are not supported anymore.
|
||||
|
||||
==== Query/filter merge
|
||||
|
||||
Elasticsearch no longer makes a difference between queries and filters in the
|
||||
|
|
|
@ -271,15 +271,15 @@ file which will resolve to an environment setting, for example:
|
|||
--------------------------------------------------
|
||||
|
||||
Additionally, for settings that you do not wish to store in the configuration
|
||||
file, you can use the value `${prompt::text}` or `${prompt::secret}` and start
|
||||
Elasticsearch in the foreground. `${prompt::secret}` has echoing disabled so
|
||||
that the value entered will not be shown in your terminal; `${prompt::text}`
|
||||
file, you can use the value `${prompt.text}` or `${prompt.secret}` and start
|
||||
Elasticsearch in the foreground. `${prompt.secret}` has echoing disabled so
|
||||
that the value entered will not be shown in your terminal; `${prompt.text}`
|
||||
will allow you to see the value as you type it in. For example:
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
node:
|
||||
name: ${prompt::text}
|
||||
name: ${prompt.text}
|
||||
--------------------------------------------------
|
||||
|
||||
On execution of the `elasticsearch` command, you will be prompted to enter
|
||||
|
@ -290,7 +290,7 @@ the actual value like so:
|
|||
Enter value for [node.name]:
|
||||
--------------------------------------------------
|
||||
|
||||
NOTE: Elasticsearch will not start if `${prompt::text}` or `${prompt::secret}`
|
||||
NOTE: Elasticsearch will not start if `${prompt.text}` or `${prompt.secret}`
|
||||
is used in the settings and the process is run as a service or in the background.
|
||||
|
||||
The location of the configuration file can be set externally using a
|
||||
|
|
|
@ -60,6 +60,7 @@ public class AzureTwoStartedNodesTest extends AbstractAzureComputeServiceTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/11533")
|
||||
public void two_nodes_should_run_using_public_ip() {
|
||||
Settings.Builder settings = Settings.settingsBuilder()
|
||||
.put(Management.SERVICE_NAME, "dummy")
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
- do:
|
||||
indices.create:
|
||||
index: testing
|
||||
body:
|
||||
settings:
|
||||
index:
|
||||
number_of_replicas: 0
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
wait_for_status: green
|
||||
- do:
|
||||
indices.flush_synced:
|
||||
index: testing
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.indices.IndicesService;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class CustomQueryParserTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
|
||||
.put("plugin.types", DummyQueryParserPlugin.class.getName()).build();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
createIndex("test");
|
||||
ensureGreen();
|
||||
client().prepareIndex("index", "type", "1").setSource("field", "value").get();
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int numberOfShards() {
|
||||
return cluster().numDataNodes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomDummyQuery() {
|
||||
assertHitCount(client().prepareSearch("index").setQuery(new DummyQueryParserPlugin.DummyQueryBuilder()).get(), 1l);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomDummyQueryWithinBooleanQuery() {
|
||||
assertHitCount(client().prepareSearch("index").setQuery(new BoolQueryBuilder().must(new DummyQueryParserPlugin.DummyQueryBuilder())).get(), 1l);
|
||||
}
|
||||
|
||||
private static IndexQueryParserService queryParser() {
|
||||
IndicesService indicesService = internalCluster().getDataNodeInstance(IndicesService.class);
|
||||
return indicesService.indexServiceSafe("index").queryParserService();
|
||||
}
|
||||
|
||||
@Test //see #11120
|
||||
public void testConstantScoreParsesFilter() throws Exception {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
Query q = queryParser.parse(constantScoreQuery(new DummyQueryParserPlugin.DummyQueryBuilder())).query();
|
||||
Query inner = ((ConstantScoreQuery) q).getQuery();
|
||||
assertThat(inner, instanceOf(DummyQueryParserPlugin.DummyQuery.class));
|
||||
assertEquals(true, ((DummyQueryParserPlugin.DummyQuery) inner).isFilter);
|
||||
}
|
||||
|
||||
@Test //see #11120
|
||||
public void testBooleanParsesFilter() throws Exception {
|
||||
IndexQueryParserService queryParser = queryParser();
|
||||
// single clause, serialized as inner object
|
||||
Query q = queryParser.parse(boolQuery()
|
||||
.should(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.must(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.filter(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.mustNot(new DummyQueryParserPlugin.DummyQueryBuilder())).query();
|
||||
assertThat(q, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bq = (BooleanQuery) q;
|
||||
assertEquals(4, bq.clauses().size());
|
||||
for (BooleanClause clause : bq.clauses()) {
|
||||
DummyQueryParserPlugin.DummyQuery dummy = (DummyQueryParserPlugin.DummyQuery) clause.getQuery();
|
||||
switch (clause.getOccur()) {
|
||||
case FILTER:
|
||||
case MUST_NOT:
|
||||
assertEquals(true, dummy.isFilter);
|
||||
break;
|
||||
case MUST:
|
||||
case SHOULD:
|
||||
assertEquals(false, dummy.isFilter);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
// multiple clauses, serialized as inner arrays
|
||||
q = queryParser.parse(boolQuery()
|
||||
.should(new DummyQueryParserPlugin.DummyQueryBuilder()).should(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.must(new DummyQueryParserPlugin.DummyQueryBuilder()).must(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.filter(new DummyQueryParserPlugin.DummyQueryBuilder()).filter(new DummyQueryParserPlugin.DummyQueryBuilder())
|
||||
.mustNot(new DummyQueryParserPlugin.DummyQueryBuilder()).mustNot(new DummyQueryParserPlugin.DummyQueryBuilder())).query();
|
||||
assertThat(q, instanceOf(BooleanQuery.class));
|
||||
bq = (BooleanQuery) q;
|
||||
assertEquals(8, bq.clauses().size());
|
||||
for (BooleanClause clause : bq.clauses()) {
|
||||
DummyQueryParserPlugin.DummyQuery dummy = (DummyQueryParserPlugin.DummyQuery) clause.getQuery();
|
||||
switch (clause.getOccur()) {
|
||||
case FILTER:
|
||||
case MUST_NOT:
|
||||
assertEquals(true, dummy.isFilter);
|
||||
break;
|
||||
case MUST:
|
||||
case SHOULD:
|
||||
assertEquals(false, dummy.isFilter);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.Weight;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesModule;
|
||||
import org.elasticsearch.plugins.AbstractPlugin;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DummyQueryParserPlugin extends AbstractPlugin {
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "dummy query";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processModule(Module module) {
|
||||
if (module instanceof IndicesQueriesModule) {
|
||||
IndicesQueriesModule indicesQueriesModule = (IndicesQueriesModule) module;
|
||||
indicesQueriesModule.addQuery(DummyQueryParserPlugin.DummyQueryParser.class);
|
||||
}
|
||||
}
|
||||
|
||||
public Settings settings() {
|
||||
return Settings.EMPTY;
|
||||
}
|
||||
|
||||
public static class DummyQueryBuilder extends QueryBuilder {
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject("dummy").endObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DummyQueryParser implements QueryParser {
|
||||
@Override
|
||||
public String[] names() {
|
||||
return new String[]{"dummy"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser.Token token = parseContext.parser().nextToken();
|
||||
assert token == XContentParser.Token.END_OBJECT;
|
||||
return new DummyQuery(parseContext.isFilter());
|
||||
}
|
||||
}
|
||||
|
||||
public static class DummyQuery extends Query {
|
||||
public final boolean isFilter;
|
||||
private final Query matchAllDocsQuery = new MatchAllDocsQuery();
|
||||
|
||||
private DummyQuery(boolean isFilter) {
|
||||
this.isFilter = isFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
|
||||
return matchAllDocsQuery.createWeight(searcher, needsScores);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue