parent
88d3527178
commit
2c3165d080
|
@ -39,8 +39,6 @@ import org.elasticsearch.common.xcontent.XContentType;
|
|||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
|
||||
|
@ -637,8 +635,6 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
|
|||
}
|
||||
|
||||
public UpdateRequest source(BytesReference source) throws Exception {
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
Map<String, Object> scriptParams = null;
|
||||
Script script = null;
|
||||
try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) {
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
|
@ -649,11 +645,8 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
|
|||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if ("script".equals(currentFieldName) && token == XContentParser.Token.START_OBJECT) {
|
||||
//here we don't have settings available, unable to throw strict deprecation exceptions
|
||||
} else if ("script".equals(currentFieldName)) {
|
||||
script = Script.parse(parser, ParseFieldMatcher.EMPTY);
|
||||
} else if ("params".equals(currentFieldName)) {
|
||||
scriptParams = parser.map();
|
||||
} else if ("scripted_upsert".equals(currentFieldName)) {
|
||||
scriptedUpsert = parser.booleanValue();
|
||||
} else if ("upsert".equals(currentFieldName)) {
|
||||
|
@ -680,16 +673,6 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
|
|||
if (fields != null) {
|
||||
fields(fields.toArray(new String[fields.size()]));
|
||||
}
|
||||
} else {
|
||||
//here we don't have settings available, unable to throw deprecation exceptions
|
||||
scriptParameterParser.token(currentFieldName, token, parser, ParseFieldMatcher.EMPTY);
|
||||
}
|
||||
}
|
||||
// Don't have a script using the new API so see if it is specified with the old API
|
||||
if (script == null) {
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
script = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), scriptParams);
|
||||
}
|
||||
}
|
||||
if (script != null) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.apache.lucene.search.Query;
|
|||
import org.apache.lucene.search.RandomAccessWeight;
|
||||
import org.apache.lucene.search.Weight;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -36,15 +35,12 @@ import org.elasticsearch.script.LeafSearchScript;
|
|||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.Script.ScriptField;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -97,11 +93,8 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder>
|
|||
|
||||
public static Optional<ScriptQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
|
||||
// also, when caching, since its isCacheable is false, will result in loading all bit set...
|
||||
Script script = null;
|
||||
Map<String, Object> params = null;
|
||||
|
||||
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
|
||||
String queryName = null;
|
||||
|
@ -116,9 +109,6 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder>
|
|||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (parseContext.getParseFieldMatcher().match(currentFieldName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseContext.getParseFieldMatcher());
|
||||
} else if (parseContext.getParseFieldMatcher().match(currentFieldName, PARAMS_FIELD)) {
|
||||
// TODO remove in 3.0 (here to support old script APIs)
|
||||
params = parser.map();
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "[script] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
@ -127,25 +117,14 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder>
|
|||
queryName = parser.text();
|
||||
} else if (parseContext.getParseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) {
|
||||
boost = parser.floatValue();
|
||||
} else if (!scriptParameterParser.token(currentFieldName, token, parser, parseContext.getParseFieldMatcher())) {
|
||||
} else if (parseContext.getParseFieldMatcher().match(currentFieldName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseContext.getParseFieldMatcher());
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "[script] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (script == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
script = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
} else if (params != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"script params must be specified inside script object in a [script] filter");
|
||||
}
|
||||
|
||||
if (script == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "script must be provided with a [script] filter");
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -30,13 +29,10 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.Template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -48,13 +44,6 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
|
|||
public static final String NAME = "template";
|
||||
public static final ParseField QUERY_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
private static final Map<String, ScriptService.ScriptType> parametersToTypes = new HashMap<>();
|
||||
static {
|
||||
parametersToTypes.put("query", ScriptService.ScriptType.INLINE);
|
||||
parametersToTypes.put("file", ScriptService.ScriptType.FILE);
|
||||
parametersToTypes.put("id", ScriptService.ScriptType.STORED);
|
||||
}
|
||||
|
||||
/** Template to fill. */
|
||||
private final Template template;
|
||||
|
||||
|
@ -73,32 +62,6 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
|
|||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param template
|
||||
* the template to use for that query.
|
||||
* @param vars
|
||||
* the parameters to fill the template with.
|
||||
* @deprecated Use {@link #TemplateQueryBuilder(Template)} instead.
|
||||
* */
|
||||
@Deprecated
|
||||
public TemplateQueryBuilder(String template, Map<String, Object> vars) {
|
||||
this(new Template(template, ScriptService.ScriptType.INLINE, null, null, vars));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param template
|
||||
* the template to use for that query.
|
||||
* @param vars
|
||||
* the parameters to fill the template with.
|
||||
* @param templateType
|
||||
* what kind of template (INLINE,FILE,ID)
|
||||
* @deprecated Use {@link #TemplateQueryBuilder(Template)} instead.
|
||||
* */
|
||||
@Deprecated
|
||||
public TemplateQueryBuilder(String template, ScriptService.ScriptType templateType, Map<String, Object> vars) {
|
||||
this(new Template(template, templateType, null, null, vars));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream.
|
||||
*/
|
||||
|
@ -118,42 +81,6 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
|
|||
template.toXContent(builder, builderParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* In the simplest case, parse template string and variables from the request,
|
||||
* compile the template and execute the template against the given variables.
|
||||
*/
|
||||
public static Optional<TemplateQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
Template template = parse(parser, parseContext.getParseFieldMatcher());
|
||||
return Optional.of(new TemplateQueryBuilder(template));
|
||||
}
|
||||
|
||||
public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher, String... parameters) throws IOException {
|
||||
Map<String, ScriptService.ScriptType> parameterMap = new HashMap<>(parametersToTypes);
|
||||
for (String parameter : parameters) {
|
||||
parameterMap.put(parameter, ScriptService.ScriptType.INLINE);
|
||||
}
|
||||
return parse(parser, parameterMap, parseFieldMatcher);
|
||||
}
|
||||
|
||||
public static Template parse(String defaultLang, XContentParser parser,
|
||||
ParseFieldMatcher parseFieldMatcher, String... parameters) throws IOException {
|
||||
Map<String, ScriptService.ScriptType> parameterMap = new HashMap<>(parametersToTypes);
|
||||
for (String parameter : parameters) {
|
||||
parameterMap.put(parameter, ScriptService.ScriptType.INLINE);
|
||||
}
|
||||
return Template.parse(parser, parameterMap, defaultLang, parseFieldMatcher);
|
||||
}
|
||||
|
||||
public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
return parse(parser, parametersToTypes, parseFieldMatcher);
|
||||
}
|
||||
|
||||
public static Template parse(XContentParser parser, Map<String, ScriptService.ScriptType> parameterMap,
|
||||
ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
return Template.parse(parser, parameterMap, parseFieldMatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
return NAME;
|
||||
|
@ -182,7 +109,7 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
|
|||
try (XContentParser qSourceParser = XContentFactory.xContent(querySource).createParser(querySource)) {
|
||||
final QueryParseContext queryParseContext = queryRewriteContext.newParseContext(qSourceParser);
|
||||
final QueryBuilder queryBuilder = queryParseContext.parseInnerQueryBuilder().orElseThrow(
|
||||
() -> new ParsingException(qSourceParser.getTokenLocation(), "inner query in [" + NAME + "] cannot be empty"));;
|
||||
() -> new ParsingException(qSourceParser.getTokenLocation(), "inner query in [" + NAME + "] cannot be empty"));
|
||||
if (boost() != DEFAULT_BOOST || queryName() != null) {
|
||||
final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
|
||||
boolQueryBuilder.must(queryBuilder);
|
||||
|
@ -191,4 +118,14 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
|
|||
return queryBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the simplest case, parse template string and variables from the request,
|
||||
* compile the template and execute the template against the given variables.
|
||||
*/
|
||||
public static Optional<TemplateQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
Template template = Template.parse(parser, parseContext.getParseFieldMatcher());
|
||||
return Optional.of(new TemplateQueryBuilder(template));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,14 +32,10 @@ import org.elasticsearch.index.query.QueryShardException;
|
|||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.Script.ScriptField;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -111,41 +107,21 @@ public class ScriptScoreFunctionBuilder extends ScoreFunctionBuilder<ScriptScore
|
|||
public static ScriptScoreFunctionBuilder fromXContent(QueryParseContext parseContext)
|
||||
throws IOException, ParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
Script script = null;
|
||||
Map<String, Object> vars = null;
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
} else {
|
||||
if (parseContext.getParseFieldMatcher().match(currentFieldName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseContext.getParseFieldMatcher());
|
||||
} else if ("params".equals(currentFieldName)) { // TODO remove in 3.0 (here to support old script APIs)
|
||||
vars = parser.map();
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), NAME + " query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if (!scriptParameterParser.token(currentFieldName, token, parser, parseContext.getParseFieldMatcher())) {
|
||||
throw new ParsingException(parser.getTokenLocation(), NAME + " query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (script == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
if (vars == null) {
|
||||
vars = new HashMap<>();
|
||||
}
|
||||
script = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), vars);
|
||||
}
|
||||
} else if (vars != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "script params must be specified inside script object");
|
||||
}
|
||||
|
||||
if (script == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), NAME + " requires 'script' field");
|
||||
}
|
||||
|
|
|
@ -33,12 +33,6 @@ import org.elasticsearch.rest.RestController;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.support.RestActions;
|
||||
import org.elasticsearch.rest.action.support.RestStatusToXContentListener;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
|
||||
|
@ -64,18 +58,6 @@ public class RestUpdateAction extends BaseRestHandler {
|
|||
updateRequest.consistencyLevel(WriteConsistencyLevel.fromString(consistencyLevel));
|
||||
}
|
||||
updateRequest.docAsUpsert(request.paramAsBoolean("doc_as_upsert", updateRequest.docAsUpsert()));
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
scriptParameterParser.parseParams(request);
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
Map<String, Object> scriptParams = new HashMap<>();
|
||||
for (Map.Entry<String, String> entry : request.params().entrySet()) {
|
||||
if (entry.getKey().startsWith("sp_")) {
|
||||
scriptParams.put(entry.getKey().substring(3), entry.getValue());
|
||||
}
|
||||
}
|
||||
updateRequest.script(new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), scriptParams));
|
||||
}
|
||||
String sField = request.param("fields");
|
||||
if (sField != null) {
|
||||
String[] sFields = Strings.splitStringByCommaToArray(sField);
|
||||
|
|
|
@ -26,24 +26,18 @@ import org.elasticsearch.script.Script.ScriptParseException;
|
|||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class AbstractScriptParser<S extends Script> {
|
||||
|
||||
protected abstract String parseInlineScript(XContentParser parser) throws IOException;
|
||||
public abstract String parseInlineScript(XContentParser parser) throws IOException;
|
||||
|
||||
protected abstract S createScript(String script, ScriptType type, String lang, Map<String, Object> params);
|
||||
|
||||
protected abstract S createSimpleScript(XContentParser parser) throws IOException;
|
||||
|
||||
@Deprecated
|
||||
protected Map<String, ScriptType> getAdditionalScriptParameters() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public S parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
|
@ -68,24 +62,24 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.INLINE.getParseField()) || parseFieldMatcher.match(currentFieldName, ScriptService.SCRIPT_INLINE)) {
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.INLINE.getParseField())) {
|
||||
type = ScriptType.INLINE;
|
||||
script = parseInlineScript(parser);
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.FILE.getParseField()) || parseFieldMatcher.match(currentFieldName, ScriptService.SCRIPT_FILE)) {
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.FILE.getParseField())) {
|
||||
type = ScriptType.FILE;
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
script = parser.text();
|
||||
} else {
|
||||
throw new ScriptParseException("expected a string value for field [{}], but found [{}]", currentFieldName, token);
|
||||
}
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.STORED.getParseField()) || parseFieldMatcher.match(currentFieldName, ScriptService.SCRIPT_ID)) {
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptType.STORED.getParseField())) {
|
||||
type = ScriptType.STORED;
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
script = parser.text();
|
||||
} else {
|
||||
throw new ScriptParseException("expected a string value for field [{}], but found [{}]", currentFieldName, token);
|
||||
}
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptField.LANG) || parseFieldMatcher.match(currentFieldName, ScriptService.SCRIPT_LANG)) {
|
||||
} else if (parseFieldMatcher.match(currentFieldName, ScriptField.LANG)) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
lang = parser.text();
|
||||
} else {
|
||||
|
@ -98,14 +92,7 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
throw new ScriptParseException("expected an object for field [{}], but found [{}]", currentFieldName, token);
|
||||
}
|
||||
} else {
|
||||
// TODO remove this in 3.0
|
||||
ScriptType paramScriptType = getAdditionalScriptParameters().get(currentFieldName);
|
||||
if (paramScriptType != null) {
|
||||
script = parseInlineScript(parser);
|
||||
type = paramScriptType;
|
||||
} else {
|
||||
throw new ScriptParseException("unexpected field [{}]", currentFieldName);
|
||||
}
|
||||
throw new ScriptParseException("unexpected field [{}]", currentFieldName);
|
||||
}
|
||||
}
|
||||
if (script == null) {
|
||||
|
@ -135,7 +122,7 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
Entry<String, Object> entry = itr.next();
|
||||
String parameterName = entry.getKey();
|
||||
Object parameterValue = entry.getValue();
|
||||
if (parseFieldMatcher.match(parameterName, ScriptField.LANG) || parseFieldMatcher.match(parameterName, ScriptService.SCRIPT_LANG)) {
|
||||
if (parseFieldMatcher.match(parameterName, ScriptField.LANG)) {
|
||||
if (parameterValue instanceof String || parameterValue == null) {
|
||||
lang = (String) parameterValue;
|
||||
if (removeMatchedEntries) {
|
||||
|
@ -153,7 +140,7 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.INLINE.getParseField()) || parseFieldMatcher.match(parameterName, ScriptService.SCRIPT_INLINE)) {
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.INLINE.getParseField())) {
|
||||
if (parameterValue instanceof String || parameterValue == null) {
|
||||
script = (String) parameterValue;
|
||||
type = ScriptType.INLINE;
|
||||
|
@ -163,7 +150,7 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.FILE.getParseField()) || parseFieldMatcher.match(parameterName, ScriptService.SCRIPT_FILE)) {
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.FILE.getParseField())) {
|
||||
if (parameterValue instanceof String || parameterValue == null) {
|
||||
script = (String) parameterValue;
|
||||
type = ScriptType.FILE;
|
||||
|
@ -173,7 +160,7 @@ public abstract class AbstractScriptParser<S extends Script> {
|
|||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.STORED.getParseField()) || parseFieldMatcher.match(parameterName, ScriptService.SCRIPT_ID)) {
|
||||
} else if (parseFieldMatcher.match(parameterName, ScriptType.STORED.getParseField())) {
|
||||
if (parameterValue instanceof String || parameterValue == null) {
|
||||
script = (String) parameterValue;
|
||||
type = ScriptType.STORED;
|
||||
|
|
|
@ -121,7 +121,7 @@ public class Script implements ToXContent, Writeable {
|
|||
}
|
||||
doWriteTo(out);
|
||||
}
|
||||
|
||||
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {};
|
||||
|
||||
/**
|
||||
|
@ -253,7 +253,7 @@ public class Script implements ToXContent, Writeable {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected String parseInlineScript(XContentParser parser) throws IOException {
|
||||
public String parseInlineScript(XContentParser parser) throws IOException {
|
||||
return parser.text();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,10 @@ import org.elasticsearch.cluster.AbstractDiffable;
|
|||
import org.elasticsearch.cluster.Diff;
|
||||
import org.elasticsearch.cluster.DiffableUtils;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
|
@ -42,8 +39,6 @@ import java.util.Collections;
|
|||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class ScriptMetaData implements MetaData.Custom {
|
||||
|
||||
|
@ -70,7 +65,10 @@ public final class ScriptMetaData implements MetaData.Custom {
|
|||
if (scriptAsBytes == null) {
|
||||
return null;
|
||||
}
|
||||
return parseStoredScript(scriptAsBytes);
|
||||
}
|
||||
|
||||
public static String parseStoredScript(BytesReference scriptAsBytes) {
|
||||
// Scripts can be stored via API in several ways:
|
||||
// 1) wrapped into a 'script' json object or field
|
||||
// 2) wrapped into a 'template' json object or field
|
||||
|
|
|
@ -1,234 +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.script;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.xcontent.ToXContent.Params;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.Script.ScriptParseException;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ScriptParameterParser {
|
||||
|
||||
public static final String FILE_SUFFIX = "_file";
|
||||
public static final String INDEXED_SUFFIX = "_id";
|
||||
|
||||
private Map<String, ScriptParameterValue> parameterValues = new HashMap<>();
|
||||
private Set<ParseField> inlineParameters;
|
||||
private Set<ParseField> fileParameters;
|
||||
private Set<ParseField> indexedParameters;
|
||||
private String lang = null;
|
||||
|
||||
public ScriptParameterParser() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public ScriptParameterParser(Set<String> parameterNames) {
|
||||
if (parameterNames == null || parameterNames.isEmpty()) {
|
||||
inlineParameters = Collections.singleton(ScriptService.SCRIPT_INLINE);
|
||||
fileParameters = Collections.singleton(ScriptService.SCRIPT_FILE);
|
||||
indexedParameters = Collections.singleton(ScriptService.SCRIPT_ID);
|
||||
} else {
|
||||
inlineParameters = new HashSet<>();
|
||||
fileParameters = new HashSet<>();
|
||||
indexedParameters = new HashSet<>();
|
||||
for (String parameterName : parameterNames) {
|
||||
if (ParseFieldMatcher.EMPTY.match(parameterName, ScriptService.SCRIPT_LANG)) {
|
||||
throw new IllegalArgumentException("lang is reserved and cannot be used as a parameter name");
|
||||
}
|
||||
inlineParameters.add(new ParseField(parameterName));
|
||||
fileParameters.add(new ParseField(parameterName + FILE_SUFFIX));
|
||||
indexedParameters.add(new ParseField(parameterName + INDEXED_SUFFIX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean token(String currentFieldName, XContentParser.Token token, XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
if (parseFieldMatcher.match(currentFieldName, ScriptService.SCRIPT_LANG)) {
|
||||
lang = parser.text();
|
||||
return true;
|
||||
} else {
|
||||
for (ParseField parameter : inlineParameters) {
|
||||
if (parseFieldMatcher.match(currentFieldName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName();
|
||||
putParameterValue(coreParameterName, parser.textOrNull(), ScriptType.INLINE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : fileParameters) {
|
||||
if (parseFieldMatcher.match(currentFieldName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(FILE_SUFFIX, "");
|
||||
putParameterValue(coreParameterName, parser.textOrNull(), ScriptType.FILE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : indexedParameters) {
|
||||
if (parseFieldMatcher.match(currentFieldName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(INDEXED_SUFFIX, "");
|
||||
putParameterValue(coreParameterName, parser.textOrNull(), ScriptType.STORED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void parseConfig(Map<String, Object> config, boolean removeMatchedEntries, ParseFieldMatcher parseFieldMatcher) {
|
||||
for (Iterator<Map.Entry<String, Object>> itr = config.entrySet().iterator(); itr.hasNext();) {
|
||||
Map.Entry<String, Object> entry = itr.next();
|
||||
String parameterName = entry.getKey();
|
||||
Object parameterValue = entry.getValue();
|
||||
if (parseFieldMatcher.match(parameterName, ScriptService.SCRIPT_LANG)) {
|
||||
if (parameterValue instanceof String || parameterValue == null) {
|
||||
lang = (String) parameterValue;
|
||||
if (removeMatchedEntries) {
|
||||
itr.remove();
|
||||
}
|
||||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
} else {
|
||||
for (ParseField parameter : inlineParameters) {
|
||||
if (parseFieldMatcher.match(parameterName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName();
|
||||
String stringValue;
|
||||
if (parameterValue instanceof String) {
|
||||
stringValue = (String) parameterValue;
|
||||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
putParameterValue(coreParameterName, stringValue, ScriptType.INLINE);
|
||||
if (removeMatchedEntries) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : fileParameters) {
|
||||
if (parseFieldMatcher.match(parameterName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(FILE_SUFFIX, "");;
|
||||
String stringValue;
|
||||
if (parameterValue instanceof String) {
|
||||
stringValue = (String) parameterValue;
|
||||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
putParameterValue(coreParameterName, stringValue, ScriptType.FILE);
|
||||
if (removeMatchedEntries) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : indexedParameters) {
|
||||
if (parseFieldMatcher.match(parameterName, parameter)) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(INDEXED_SUFFIX, "");
|
||||
String stringValue = null;
|
||||
if (parameterValue instanceof String) {
|
||||
stringValue = (String) parameterValue;
|
||||
} else {
|
||||
throw new ScriptParseException("Value must be of type String: [" + parameterName + "]");
|
||||
}
|
||||
putParameterValue(coreParameterName, stringValue, ScriptType.STORED);
|
||||
if (removeMatchedEntries) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putParameterValue(String coreParameterName, String script, ScriptType scriptType) {
|
||||
if (parameterValues.get(coreParameterName) == null) {
|
||||
parameterValues.put(coreParameterName, new ScriptParameterValue(script, scriptType));
|
||||
} else {
|
||||
throw new ScriptParseException("Only one of [" + coreParameterName + ", " + coreParameterName
|
||||
+ FILE_SUFFIX + ", " + coreParameterName + INDEXED_SUFFIX + "] is allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
public void parseParams(Params params) {
|
||||
lang = params.param(ScriptService.SCRIPT_LANG.getPreferredName());
|
||||
for (ParseField parameter : inlineParameters) {
|
||||
String value = params.param(parameter.getPreferredName());
|
||||
if (value != null) {
|
||||
String coreParameterName = parameter.getPreferredName();
|
||||
putParameterValue(coreParameterName, value, ScriptType.INLINE);
|
||||
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : fileParameters) {
|
||||
String value = params.param(parameter.getPreferredName());
|
||||
if (value != null) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(FILE_SUFFIX, "");
|
||||
putParameterValue(coreParameterName, value, ScriptType.FILE);
|
||||
|
||||
}
|
||||
}
|
||||
for (ParseField parameter : indexedParameters) {
|
||||
String value = params.param(parameter.getPreferredName());
|
||||
if (value != null) {
|
||||
String coreParameterName = parameter.getPreferredName().replace(INDEXED_SUFFIX, "");
|
||||
putParameterValue(coreParameterName, value, ScriptType.STORED);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ScriptParameterValue getDefaultScriptParameterValue() {
|
||||
return getScriptParameterValue(ScriptService.SCRIPT_INLINE.getPreferredName());
|
||||
}
|
||||
|
||||
public ScriptParameterValue getScriptParameterValue(String parameterName) {
|
||||
return parameterValues.get(parameterName);
|
||||
}
|
||||
|
||||
public String lang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public static class ScriptParameterValue {
|
||||
private String script;
|
||||
private ScriptType scriptType;
|
||||
|
||||
public ScriptParameterValue(String script, ScriptType scriptType) {
|
||||
this.script = script;
|
||||
this.scriptType = scriptType;
|
||||
}
|
||||
|
||||
public String script() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public ScriptType scriptType() {
|
||||
return scriptType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,10 +52,7 @@ import org.elasticsearch.common.settings.Setting.Property;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.query.TemplateQueryBuilder;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
|
@ -109,31 +106,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
|
||||
private ClusterState clusterState;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link org.elasticsearch.script.Script.ScriptField} instead. This should be removed in
|
||||
* 2.0
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ParseField SCRIPT_LANG = new ParseField("lang","script_lang");
|
||||
/**
|
||||
* @deprecated Use {@link ScriptType#getParseField()} instead. This should
|
||||
* be removed in 2.0
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ParseField SCRIPT_FILE = new ParseField("script_file");
|
||||
/**
|
||||
* @deprecated Use {@link ScriptType#getParseField()} instead. This should
|
||||
* be removed in 2.0
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ParseField SCRIPT_ID = new ParseField("script_id");
|
||||
/**
|
||||
* @deprecated Use {@link ScriptType#getParseField()} instead. This should
|
||||
* be removed in 2.0
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ParseField SCRIPT_INLINE = new ParseField("script");
|
||||
|
||||
public ScriptService(Settings settings, Environment env,
|
||||
ResourceWatcherService resourceWatcherService, ScriptEngineRegistry scriptEngineRegistry,
|
||||
ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings) throws IOException {
|
||||
|
@ -346,47 +318,42 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
|
|||
return script;
|
||||
}
|
||||
|
||||
void validate(String id, String scriptLang, BytesReference scriptBytes) {
|
||||
void validateStoredScript(String id, String scriptLang, BytesReference scriptBytes) {
|
||||
validateScriptSize(id, scriptBytes.length());
|
||||
try (XContentParser parser = XContentFactory.xContent(scriptBytes).createParser(scriptBytes)) {
|
||||
parser.nextToken();
|
||||
Template template = TemplateQueryBuilder.parse(scriptLang, parser, parseFieldMatcher, "params", "script", "template");
|
||||
if (Strings.hasLength(template.getScript())) {
|
||||
//Just try and compile it
|
||||
try {
|
||||
ScriptEngineService scriptEngineService = getScriptEngineServiceForLang(scriptLang);
|
||||
//we don't know yet what the script will be used for, but if all of the operations for this lang with
|
||||
//indexed scripts are disabled, it makes no sense to even compile it.
|
||||
if (isAnyScriptContextEnabled(scriptLang, ScriptType.STORED)) {
|
||||
Object compiled = scriptEngineService.compile(id, template.getScript(), Collections.emptyMap());
|
||||
if (compiled == null) {
|
||||
throw new IllegalArgumentException("Unable to parse [" + template.getScript() +
|
||||
"] lang [" + scriptLang + "] (ScriptService.compile returned null)");
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"skipping compile of script [{}], lang [{}] as all scripted operations are disabled for indexed scripts",
|
||||
template.getScript(), scriptLang);
|
||||
String script = ScriptMetaData.parseStoredScript(scriptBytes);
|
||||
if (Strings.hasLength(scriptBytes)) {
|
||||
//Just try and compile it
|
||||
try {
|
||||
ScriptEngineService scriptEngineService = getScriptEngineServiceForLang(scriptLang);
|
||||
//we don't know yet what the script will be used for, but if all of the operations for this lang with
|
||||
//indexed scripts are disabled, it makes no sense to even compile it.
|
||||
if (isAnyScriptContextEnabled(scriptLang, ScriptType.STORED)) {
|
||||
Object compiled = scriptEngineService.compile(id, script, Collections.emptyMap());
|
||||
if (compiled == null) {
|
||||
throw new IllegalArgumentException("Unable to parse [" + script + "] lang [" + scriptLang +
|
||||
"] (ScriptService.compile returned null)");
|
||||
}
|
||||
} catch (ScriptException good) {
|
||||
// TODO: remove this when all script engines have good exceptions!
|
||||
throw good; // its already good!
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Unable to parse [" + template.getScript() +
|
||||
"] lang [" + scriptLang + "]", e);
|
||||
} else {
|
||||
logger.warn(
|
||||
"skipping compile of script [{}], lang [{}] as all scripted operations are disabled for indexed scripts",
|
||||
script, scriptLang);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to find script in : " + scriptBytes.utf8ToString());
|
||||
} catch (ScriptException good) {
|
||||
// TODO: remove this when all script engines have good exceptions!
|
||||
throw good; // its already good!
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Unable to parse [" + script +
|
||||
"] lang [" + scriptLang + "]", e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("failed to parse template script", e);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to find script in : " + scriptBytes.utf8ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void storeScript(ClusterService clusterService, PutStoredScriptRequest request, ActionListener<PutStoredScriptResponse> listener) {
|
||||
String scriptLang = validateScriptLanguage(request.scriptLang());
|
||||
//verify that the script compiles
|
||||
validate(request.id(), scriptLang, request.script());
|
||||
validateStoredScript(request.id(), scriptLang, request.script());
|
||||
clusterService.submitStateUpdateTask("put-script-" + request.id(), new AckedClusterStateUpdateTask<PutStoredScriptResponse>(request, listener) {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.elasticsearch.common.xcontent.XContentType;
|
|||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class Template extends Script {
|
||||
|
@ -112,21 +111,11 @@ public class Template extends Script {
|
|||
}
|
||||
|
||||
public static Script parse(Map<String, Object> config, boolean removeMatchedEntries, ParseFieldMatcher parseFieldMatcher) {
|
||||
return new TemplateParser(Collections.emptyMap(), DEFAULT_LANG).parse(config, removeMatchedEntries, parseFieldMatcher);
|
||||
return new TemplateParser(DEFAULT_LANG).parse(config, removeMatchedEntries, parseFieldMatcher);
|
||||
}
|
||||
|
||||
public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
return new TemplateParser(Collections.emptyMap(), DEFAULT_LANG).parse(parser, parseFieldMatcher);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Template parse(XContentParser parser, Map<String, ScriptType> additionalTemplateFieldNames, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
return new TemplateParser(additionalTemplateFieldNames, DEFAULT_LANG).parse(parser, parseFieldMatcher);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Template parse(XContentParser parser, Map<String, ScriptType> additionalTemplateFieldNames, String defaultLang, ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
return new TemplateParser(additionalTemplateFieldNames, defaultLang).parse(parser, parseFieldMatcher);
|
||||
return new TemplateParser(DEFAULT_LANG).parse(parser, parseFieldMatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,11 +139,9 @@ public class Template extends Script {
|
|||
private static class TemplateParser extends AbstractScriptParser<Template> {
|
||||
|
||||
private XContentType contentType = null;
|
||||
private final Map<String, ScriptType> additionalTemplateFieldNames;
|
||||
private String defaultLang;
|
||||
|
||||
public TemplateParser(Map<String, ScriptType> additionalTemplateFieldNames, String defaultLang) {
|
||||
this.additionalTemplateFieldNames = additionalTemplateFieldNames;
|
||||
public TemplateParser(String defaultLang) {
|
||||
this.defaultLang = defaultLang;
|
||||
}
|
||||
|
||||
|
@ -169,7 +156,7 @@ public class Template extends Script {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected String parseInlineScript(XContentParser parser) throws IOException {
|
||||
public String parseInlineScript(XContentParser parser) throws IOException {
|
||||
if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
|
||||
contentType = parser.contentType();
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(contentType);
|
||||
|
@ -179,11 +166,6 @@ public class Template extends Script {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ScriptType> getAdditionalScriptParameters() {
|
||||
return additionalTemplateFieldNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScriptLang() {
|
||||
return defaultLang;
|
||||
|
|
|
@ -33,16 +33,12 @@ import org.elasticsearch.script.ExecutableScript;
|
|||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.Script.ScriptField;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ScriptHeuristic extends SignificanceHeuristic {
|
||||
|
@ -155,37 +151,19 @@ public class ScriptHeuristic extends SignificanceHeuristic {
|
|||
String heuristicName = parser.currentName();
|
||||
Script script = null;
|
||||
XContentParser.Token token;
|
||||
Map<String, Object> params = null;
|
||||
String currentFieldName = null;
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token.equals(XContentParser.Token.FIELD_NAME)) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
} else {
|
||||
if (parseFieldMatcher.match(currentFieldName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseFieldMatcher);
|
||||
} else if ("params".equals(currentFieldName)) { // TODO remove in 3.0 (here to support old script APIs)
|
||||
params = parser.map();
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] significance heuristic. unknown object [{}]", heuristicName, currentFieldName);
|
||||
}
|
||||
} else if (!scriptParameterParser.token(currentFieldName, token, parser, parseFieldMatcher)) {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] significance heuristic. unknown field [{}]", heuristicName, currentFieldName);
|
||||
}
|
||||
}
|
||||
|
||||
if (script == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
script = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
} else if (params != null) {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] significance heuristic. script params must be specified inside script object", heuristicName);
|
||||
}
|
||||
|
||||
if (script == null) {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] significance heuristic. no script found in script_heuristic", heuristicName);
|
||||
}
|
||||
|
|
|
@ -27,12 +27,10 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation.Type;
|
||||
import org.elasticsearch.search.aggregations.AggregatorFactory;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation.Type;
|
||||
import org.elasticsearch.search.aggregations.support.AggregationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -52,7 +50,6 @@ public class ScriptedMetricAggregationBuilder extends AbstractAggregationBuilder
|
|||
private static final ParseField COMBINE_SCRIPT_FIELD = new ParseField("combine_script");
|
||||
private static final ParseField REDUCE_SCRIPT_FIELD = new ParseField("reduce_script");
|
||||
private static final ParseField PARAMS_FIELD = new ParseField("params");
|
||||
private static final ParseField REDUCE_PARAMS_FIELD = new ParseField("reduce_params");
|
||||
|
||||
private Script initScript;
|
||||
private Script mapScript;
|
||||
|
@ -222,7 +219,6 @@ public class ScriptedMetricAggregationBuilder extends AbstractAggregationBuilder
|
|||
Script combineScript = null;
|
||||
Script reduceScript = null;
|
||||
Map<String, Object> params = null;
|
||||
Map<String, Object> reduceParams = null;
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
Set<String> scriptParameters = new HashSet<>();
|
||||
|
@ -230,13 +226,12 @@ public class ScriptedMetricAggregationBuilder extends AbstractAggregationBuilder
|
|||
scriptParameters.add(MAP_SCRIPT_FIELD.getPreferredName());
|
||||
scriptParameters.add(COMBINE_SCRIPT_FIELD.getPreferredName());
|
||||
scriptParameters.add(REDUCE_SCRIPT_FIELD.getPreferredName());
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser(scriptParameters);
|
||||
|
||||
XContentParser parser = context.parser();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
} else if (token == XContentParser.Token.START_OBJECT || token == XContentParser.Token.VALUE_STRING) {
|
||||
if (context.getParseFieldMatcher().match(currentFieldName, INIT_SCRIPT_FIELD)) {
|
||||
initScript = Script.parse(parser, context.getParseFieldMatcher());
|
||||
} else if (context.getParseFieldMatcher().match(currentFieldName, MAP_SCRIPT_FIELD)) {
|
||||
|
@ -245,64 +240,18 @@ public class ScriptedMetricAggregationBuilder extends AbstractAggregationBuilder
|
|||
combineScript = Script.parse(parser, context.getParseFieldMatcher());
|
||||
} else if (context.getParseFieldMatcher().match(currentFieldName, REDUCE_SCRIPT_FIELD)) {
|
||||
reduceScript = Script.parse(parser, context.getParseFieldMatcher());
|
||||
} else if (context.getParseFieldMatcher().match(currentFieldName, PARAMS_FIELD)) {
|
||||
} else if (token == XContentParser.Token.START_OBJECT &&
|
||||
context.getParseFieldMatcher().match(currentFieldName, PARAMS_FIELD)) {
|
||||
params = parser.map();
|
||||
} else if (context.getParseFieldMatcher().match(currentFieldName, REDUCE_PARAMS_FIELD)) {
|
||||
reduceParams = parser.map();
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"Unknown key for a " + token + " in [" + aggregationName + "]: [" + currentFieldName + "].");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if (!scriptParameterParser.token(currentFieldName, token, parser, context.getParseFieldMatcher())) {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"Unknown key for a " + token + " in [" + aggregationName + "]: [" + currentFieldName + "].");
|
||||
}
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "Unexpected token " + token + " in [" + aggregationName + "].");
|
||||
}
|
||||
}
|
||||
|
||||
if (initScript == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getScriptParameterValue(INIT_SCRIPT_FIELD.getPreferredName());
|
||||
if (scriptValue != null) {
|
||||
initScript = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
} else if (initScript.getParams() != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "init_script params are not supported. Parameters for the "
|
||||
+ "init_script must be specified in the params field on the scripted_metric aggregator not inside the init_script "
|
||||
+ "object");
|
||||
}
|
||||
|
||||
if (mapScript == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getScriptParameterValue(MAP_SCRIPT_FIELD.getPreferredName());
|
||||
if (scriptValue != null) {
|
||||
mapScript = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
} else if (mapScript.getParams() != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "map_script params are not supported. Parameters for the map_script "
|
||||
+ "must be specified in the params field on the scripted_metric aggregator not inside the map_script object");
|
||||
}
|
||||
|
||||
if (combineScript == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getScriptParameterValue(COMBINE_SCRIPT_FIELD.getPreferredName());
|
||||
if (scriptValue != null) {
|
||||
combineScript = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
} else if (combineScript.getParams() != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"combine_script params are not supported. Parameters for the "
|
||||
+ "combine_script must be specified in the params field on the scripted_metric aggregator not inside the "
|
||||
+ "combine_script object");
|
||||
}
|
||||
|
||||
if (reduceScript == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getScriptParameterValue(REDUCE_SCRIPT_FIELD.getPreferredName());
|
||||
if (scriptValue != null) {
|
||||
reduceScript = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), reduceParams);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapScript == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "map_script field is required in [" + aggregationName + "].");
|
||||
}
|
||||
|
|
|
@ -49,8 +49,6 @@ import org.elasticsearch.script.LeafSearchScript;
|
|||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.Script.ScriptField;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptParameterParser;
|
||||
import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.DocValueFormat;
|
||||
import org.elasticsearch.search.MultiValueMode;
|
||||
|
@ -74,7 +72,6 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
public static final ParseField SORTMODE_FIELD = new ParseField("mode");
|
||||
public static final ParseField NESTED_PATH_FIELD = new ParseField("nested_path");
|
||||
public static final ParseField NESTED_FILTER_FIELD = new ParseField("nested_filter");
|
||||
public static final ParseField PARAMS_FIELD = new ParseField("params");
|
||||
|
||||
private final Script script;
|
||||
|
||||
|
@ -231,7 +228,6 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
* in '{ "foo": { "order" : "asc"} }'. When parsing the inner object, the field name can be passed in via this argument
|
||||
*/
|
||||
public static ScriptSortBuilder fromXContent(QueryParseContext context, String elementName) throws IOException {
|
||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||
XContentParser parser = context.parser();
|
||||
ParseFieldMatcher parseField = context.getParseFieldMatcher();
|
||||
Script script = null;
|
||||
|
@ -240,7 +236,6 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
SortOrder order = null;
|
||||
Optional<QueryBuilder> nestedFilter = Optional.empty();
|
||||
String nestedPath = null;
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
|
||||
XContentParser.Token token;
|
||||
String currentName = parser.currentName();
|
||||
|
@ -250,8 +245,6 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (parseField.match(currentName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseField);
|
||||
} else if (parseField.match(currentName, PARAMS_FIELD)) {
|
||||
params = parser.map();
|
||||
} else if (parseField.match(currentName, NESTED_FILTER_FIELD)) {
|
||||
nestedFilter = context.parseInnerQueryBuilder();
|
||||
} else {
|
||||
|
@ -260,14 +253,14 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
} else if (token.isValue()) {
|
||||
if (parseField.match(currentName, ORDER_FIELD)) {
|
||||
order = SortOrder.fromString(parser.text());
|
||||
} else if (scriptParameterParser.token(currentName, token, parser, parseField)) {
|
||||
// Do Nothing (handled by ScriptParameterParser
|
||||
} else if (parseField.match(currentName, TYPE_FIELD)) {
|
||||
type = ScriptSortType.fromString(parser.text());
|
||||
} else if (parseField.match(currentName, SORTMODE_FIELD)) {
|
||||
sortMode = SortMode.fromString(parser.text());
|
||||
} else if (parseField.match(currentName, NESTED_PATH_FIELD)) {
|
||||
nestedPath = parser.text();
|
||||
} else if (parseField.match(currentName, ScriptField.SCRIPT)) {
|
||||
script = Script.parse(parser, parseField);
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "[" + NAME + "] failed to parse field [" + currentName + "]");
|
||||
}
|
||||
|
@ -276,16 +269,6 @@ public class ScriptSortBuilder extends SortBuilder<ScriptSortBuilder> {
|
|||
}
|
||||
}
|
||||
|
||||
if (script == null) { // Didn't find anything using the new API so try using the old one instead
|
||||
ScriptParameterValue scriptValue = scriptParameterParser.getDefaultScriptParameterValue();
|
||||
if (scriptValue != null) {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
script = new Script(scriptValue.script(), scriptValue.scriptType(), scriptParameterParser.lang(), params);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptSortBuilder result = new ScriptSortBuilder(script, type);
|
||||
if (order != null) {
|
||||
result.order(order);
|
||||
|
|
|
@ -59,6 +59,18 @@ public class UpdateRequestTests extends ESTestCase {
|
|||
Map<String, Object> params = script.getParams();
|
||||
assertThat(params, nullValue());
|
||||
|
||||
// simple verbose script
|
||||
request.source(XContentFactory.jsonBuilder().startObject()
|
||||
.startObject("script").field("inline", "script1").endObject()
|
||||
.endObject());
|
||||
script = request.script();
|
||||
assertThat(script, notNullValue());
|
||||
assertThat(script.getScript(), equalTo("script1"));
|
||||
assertThat(script.getType(), equalTo(ScriptType.INLINE));
|
||||
assertThat(script.getLang(), nullValue());
|
||||
params = script.getParams();
|
||||
assertThat(params, nullValue());
|
||||
|
||||
// script with params
|
||||
request = new UpdateRequest("test", "type", "1");
|
||||
request.source(XContentFactory.jsonBuilder().startObject().startObject("script").field("inline", "script1").startObject("params")
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ScriptQueryBuilderTests extends AbstractQueryTestCase<ScriptQueryBu
|
|||
expectThrows(IllegalArgumentException.class, () -> new ScriptQueryBuilder((Script) null));
|
||||
}
|
||||
|
||||
public void testFromJson() throws IOException {
|
||||
public void testFromJsonVerbose() throws IOException {
|
||||
String json =
|
||||
"{\n" +
|
||||
" \"script\" : {\n" +
|
||||
|
@ -67,4 +67,18 @@ public class ScriptQueryBuilderTests extends AbstractQueryTestCase<ScriptQueryBu
|
|||
|
||||
assertEquals(json, "mockscript", parsed.script().getLang());
|
||||
}
|
||||
|
||||
public void testFromJson() throws IOException {
|
||||
String json =
|
||||
"{\n" +
|
||||
" \"script\" : {\n" +
|
||||
" \"script\" : \"5\"," +
|
||||
" \"boost\" : 1.0,\n" +
|
||||
" \"_name\" : \"PcKdEyPOmR\"\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
ScriptQueryBuilder parsed = (ScriptQueryBuilder) parseQuery(json);
|
||||
assertEquals(json, "5", parsed.script().getScript());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
|
|||
|
||||
public void testRawEscapedTemplate() throws IOException {
|
||||
String expectedTemplateString = "{\"match_{{template}}\": {}}\"";
|
||||
String query = "{\"template\": {\"query\": \"{\\\"match_{{template}}\\\": {}}\\\"\",\"params\" : {\"template\" : \"all\"}}}";
|
||||
String query = "{\"template\": {\"inline\": \"{\\\"match_{{template}}\\\": {}}\\\"\",\"params\" : {\"template\" : \"all\"}}}";
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("template", "all");
|
||||
QueryBuilder expectedBuilder = new TemplateQueryBuilder(new Template(expectedTemplateString, ScriptType.INLINE, null, null,
|
||||
|
@ -110,7 +110,7 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
|
|||
|
||||
public void testRawTemplate() throws IOException {
|
||||
String expectedTemplateString = "{\"match_{{template}}\":{}}";
|
||||
String query = "{\"template\": {\"query\": {\"match_{{template}}\": {}},\"params\" : {\"template\" : \"all\"}}}";
|
||||
String query = "{\"template\": {\"inline\": {\"match_{{template}}\": {}},\"params\" : {\"template\" : \"all\"}}}";
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("template", "all");
|
||||
QueryBuilder expectedBuilder = new TemplateQueryBuilder(new Template(expectedTemplateString, ScriptType.INLINE, null,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,7 +44,6 @@ import java.nio.file.Path;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
|
@ -444,12 +443,12 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
int maxSize = 0xFFFF;
|
||||
buildScriptService(Settings.EMPTY);
|
||||
// allowed
|
||||
scriptService.validate("_id", "test", new BytesArray("{\"script\":\"" + randomAsciiOfLength(maxSize - 13) + "\"}"));
|
||||
scriptService.validateStoredScript("_id", "test", new BytesArray("{\"script\":\"" + randomAsciiOfLength(maxSize - 13) + "\"}"));
|
||||
|
||||
// disallowed
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> {
|
||||
scriptService.validate("_id", "test", new BytesArray("{\"script\":\"" + randomAsciiOfLength(maxSize - 12) + "\"}"));
|
||||
scriptService.validateStoredScript("_id", "test", new BytesArray("{\"script\":\"" + randomAsciiOfLength(maxSize - 12) + "\"}"));
|
||||
});
|
||||
assertThat(e.getMessage(), equalTo(
|
||||
"Limit of script size in bytes [" + maxSize+ "] has been exceeded for script [_id] with size [" + (maxSize + 1) + "]"));
|
||||
|
|
|
@ -192,16 +192,13 @@ public class ScriptSortBuilderTests extends AbstractSortTestCase<ScriptSortBuild
|
|||
assertNull(builder.getNestedPath());
|
||||
}
|
||||
|
||||
public void testParseJsonOldStyle() throws IOException {
|
||||
public void testParseJson_simple() throws IOException {
|
||||
String scriptSort = "{\n" +
|
||||
"\"_script\" : {\n" +
|
||||
"\"type\" : \"number\",\n" +
|
||||
"\"script\" : \"doc['field_name'].value * factor\",\n" +
|
||||
"\"params\" : {\n" +
|
||||
"\"factor\" : 1.1\n" +
|
||||
"},\n" +
|
||||
"\"mode\" : \"max\",\n" +
|
||||
"\"order\" : \"asc\"\n" +
|
||||
"\"type\" : \"number\",\n" +
|
||||
"\"script\" : \"doc['field_name'].value\",\n" +
|
||||
"\"mode\" : \"max\",\n" +
|
||||
"\"order\" : \"asc\"\n" +
|
||||
"} }\n";
|
||||
XContentParser parser = XContentFactory.xContent(scriptSort).createParser(scriptSort);
|
||||
parser.nextToken();
|
||||
|
@ -210,9 +207,9 @@ public class ScriptSortBuilderTests extends AbstractSortTestCase<ScriptSortBuild
|
|||
|
||||
QueryParseContext context = new QueryParseContext(indicesQueriesRegistry, parser, ParseFieldMatcher.STRICT);
|
||||
ScriptSortBuilder builder = ScriptSortBuilder.fromXContent(context, null);
|
||||
assertEquals("doc['field_name'].value * factor", builder.script().getScript());
|
||||
assertEquals("doc['field_name'].value", builder.script().getScript());
|
||||
assertNull(builder.script().getLang());
|
||||
assertEquals(1.1, builder.script().getParams().get("factor"));
|
||||
assertNull(builder.script().getParams());
|
||||
assertEquals(ScriptType.INLINE, builder.script().getType());
|
||||
assertEquals(ScriptSortType.NUMBER, builder.type());
|
||||
assertEquals(SortOrder.ASC, builder.order());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ "update" : {"_id" : "1", "_retry_on_conflict" : 2} }
|
||||
{ "doc" : {"field" : "value"} }
|
||||
{ "update" : { "_id" : "0", "_type" : "type1", "_index" : "index1" } }
|
||||
{ "script" : "counter += param1", "lang" : "javascript", "params" : {"param1" : 1}, "upsert" : {"counter" : 1}}
|
||||
{ "script" : { "inline" : "counter += param1", "lang" : "javascript", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
|
||||
{ "delete" : { "_id" : "2" } }
|
||||
{ "create" : { "_id" : "3" } }
|
||||
{ "field1" : "value3" }
|
||||
|
|
|
@ -1,6 +1,186 @@
|
|||
[[breaking_50_scripting]]
|
||||
=== Script related changes
|
||||
|
||||
==== Removed 1.x script and template syntax
|
||||
|
||||
The deprecated 1.x syntax of defining inline scripts / templates and referring to file or index base scripts / templates
|
||||
have been removed.
|
||||
|
||||
The `script` and `params` string parameters can no longer be used and instead the `script` object syntax must be used.
|
||||
This applies for the update api, script sort, `script_score` function, `script` query, `scripted_metric` aggregation and
|
||||
`script_heuristic` aggregation.
|
||||
|
||||
So this usage of inline scripts is no longer allowed:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"lang": "groovy",
|
||||
"script": "Math.log(_score * 2) + my_modifier",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
and instead this syntax must be used:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "groovy",
|
||||
"inline": "Math.log(_score * 2) + my_modifier",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
The `script` or `script_file` parameter can no longer be used to refer to file based scripts and templates and instead
|
||||
`file` must be used.
|
||||
|
||||
This usage of referring to file based scripts is no longer valid:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"script": "calculate-score",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
This usage is valid:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"lang": "groovy",
|
||||
"file": "calculate-score",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
The `script_id` parameter can no longer be used the refer to indexed based scripts and templates and instead `id` must
|
||||
be used.
|
||||
|
||||
This usage of referring to indexed scripts is no longer valid:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"script_id": "indexedCalculateScore",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
This usage is valid:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"script_score": {
|
||||
"script": {
|
||||
"id": "indexedCalculateScore",
|
||||
"lang" : "groovy",
|
||||
"params": {
|
||||
"my_modifier": 8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
====== Template query
|
||||
|
||||
The `query` field in the `template` query can no longer be used.
|
||||
This 1.x syntax can no longer be used:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"query": {
|
||||
"template": {
|
||||
"query": {"match_{{template}}": {}},
|
||||
"params" : {
|
||||
"template" : "all"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
and instead the following syntax should be used:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"query": {
|
||||
"template": {
|
||||
"inline": {"match_{{template}}": {}},
|
||||
"params" : {
|
||||
"template" : "all"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
===== Search templates:
|
||||
|
||||
The top level `template` field in the search template api has been replaced with consistent template / script object
|
||||
syntax. This 1.x syntax can no longer be used:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"template" : {
|
||||
"query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
|
||||
"size" : "{{my_size}}"
|
||||
},
|
||||
"params" : {
|
||||
"my_field" : "foo",
|
||||
"my_value" : "bar",
|
||||
"my_size" : 5
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
and instead the following syntax should be used:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
{
|
||||
"inline" : {
|
||||
"query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
|
||||
"size" : "{{my_size}}"
|
||||
},
|
||||
"params" : {
|
||||
"my_field" : "foo",
|
||||
"my_value" : "bar",
|
||||
"my_size" : 5
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
|
||||
==== Indexed scripts and templates
|
||||
|
||||
Indexed scripts and templates have been replaced by <<modules-scripting-stored-scripts,stored scripts>>
|
||||
|
@ -13,8 +193,8 @@ If scripts are really large, other options like native scripts should be conside
|
|||
Previously indexed scripts in the `.scripts` index will not be used any more as
|
||||
Elasticsearch will now try to fetch the scripts from the cluster state. Upon upgrading
|
||||
to 5.x the `.scripts` index will remain to exist, so it can be used by a script to migrate
|
||||
the stored scripts from the `.scripts` index into the cluster state. The format of the scripts
|
||||
hasn't changed.
|
||||
the stored scripts from the `.scripts` index into the cluster state. The current format of the scripts
|
||||
and templates hasn't been changed, only the 1.x format has been removed.
|
||||
|
||||
===== Python migration script
|
||||
|
||||
|
@ -104,3 +284,7 @@ engine doing this was the Javascript engine, which registered "js" and
|
|||
|
||||
The Javascript engine previously registered "js" and "javascript". It now only
|
||||
registers the "js" file extension for on-disk scripts.
|
||||
|
||||
==== Removed scripting query string parameters from update rest api
|
||||
|
||||
The `script`, `script_id` and `scripting_upsert` query string parameters have been removed from the update api.
|
||||
|
|
|
@ -455,16 +455,21 @@ public class BulkTests extends ESIntegTestCase {
|
|||
byte[] addParent = new BytesArray("{\"index\" : { \"_index\" : \"test\", \"_type\" : \"parent\", \"_id\" : \"parent1\"}}\n" +
|
||||
"{\"field1\" : \"value1\"}\n").array();
|
||||
|
||||
byte[] addChild = new BytesArray("{\"update\" : { \"_id\" : \"child1\", \"_type\" : \"child\", \"_index\" : \"test\", \"parent\" : \"parent1\"} }\n" +
|
||||
byte[] addChild1 = new BytesArray("{\"update\" : { \"_id\" : \"child1\", \"_type\" : \"child\", \"_index\" : \"test\", \"parent\" : \"parent1\"} }\n" +
|
||||
"{ \"script\" : {\"inline\" : \"ctx._source.field2 = 'value2'\"}, \"upsert\" : {\"field1\" : \"value1\"}}\n").array();
|
||||
|
||||
byte[] addChild2 = new BytesArray("{\"update\" : { \"_id\" : \"child1\", \"_type\" : \"child\", \"_index\" : \"test\", \"parent\" : \"parent1\"} }\n" +
|
||||
"{ \"script\" : \"ctx._source.field2 = 'value2'\", \"upsert\" : {\"field1\" : \"value1\"}}\n").array();
|
||||
|
||||
builder.add(addParent, 0, addParent.length);
|
||||
builder.add(addChild, 0, addChild.length);
|
||||
builder.add(addChild1, 0, addChild1.length);
|
||||
builder.add(addChild2, 0, addChild2.length);
|
||||
|
||||
BulkResponse bulkResponse = builder.get();
|
||||
assertThat(bulkResponse.getItems().length, equalTo(2));
|
||||
assertThat(bulkResponse.getItems().length, equalTo(3));
|
||||
assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[2].isFailed(), equalTo(false));
|
||||
|
||||
client().admin().indices().prepareRefresh("test").get();
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
index: test_1
|
||||
type: test
|
||||
id: 1
|
||||
script: "1"
|
||||
body:
|
||||
lang: groovy
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
lang: groovy
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
|
||||
- match: { _index: test_1 }
|
||||
- match: { _type: test }
|
||||
|
@ -43,8 +43,10 @@
|
|||
index: test_1
|
||||
type: test
|
||||
id: 1
|
||||
lang: groovy
|
||||
script: "ctx._source.foo = 'yyy'"
|
||||
body:
|
||||
script:
|
||||
lang: groovy
|
||||
inline: "ctx._source.foo = 'yyy'"
|
||||
|
||||
- match: { _index: test_1 }
|
||||
- match: { _type: test }
|
||||
|
@ -67,9 +69,10 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "1"
|
||||
lang: "doesnotexist"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "1"
|
||||
lang: "doesnotexist"
|
||||
params: { bar: 'xxx' }
|
||||
|
||||
- do:
|
||||
catch: /script_lang not supported \[doesnotexist\]/
|
||||
|
@ -77,6 +80,8 @@
|
|||
index: test_1
|
||||
type: test
|
||||
id: 1
|
||||
lang: doesnotexist
|
||||
script: "1"
|
||||
body:
|
||||
script:
|
||||
lang: doesnotexist
|
||||
inline: "1"
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
|
||||
- do:
|
||||
|
@ -29,8 +30,9 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
|
||||
- do:
|
||||
|
@ -47,8 +49,9 @@
|
|||
type: test
|
||||
id: 2
|
||||
body:
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
scripted_upsert: true
|
||||
|
||||
|
|
|
@ -31,8 +31,9 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
|
||||
- do:
|
||||
update:
|
||||
|
@ -41,5 +42,6 @@
|
|||
id: 1
|
||||
ignore: 404
|
||||
body:
|
||||
script: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = bar"
|
||||
params: { bar: 'xxx' }
|
||||
|
|
|
@ -153,7 +153,7 @@ public class TemplateQueryParserTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testParser() throws IOException {
|
||||
String templateString = "{" + "\"query\":{\"match_{{template}}\": {}}," + "\"params\":{\"template\":\"all\"}" + "}";
|
||||
String templateString = "{" + "\"inline\":{\"match_{{template}}\": {}}," + "\"params\":{\"template\":\"all\"}" + "}";
|
||||
|
||||
XContentParser templateSourceParser = XContentFactory.xContent(templateString).createParser(templateString);
|
||||
QueryShardContext context = contextFactory.get();
|
||||
|
|
|
@ -26,12 +26,9 @@ import org.elasticsearch.action.search.template.SearchTemplateAction;
|
|||
import org.elasticsearch.action.search.template.SearchTemplateRequest;
|
||||
import org.elasticsearch.action.search.template.SearchTemplateRequestBuilder;
|
||||
import org.elasticsearch.action.search.template.SearchTemplateResponse;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.TemplateQueryBuilder;
|
||||
|
@ -158,12 +155,6 @@ public class TemplateQueryTests extends ESIntegTestCase {
|
|||
assertHitCount(response.getResponse(), 2);
|
||||
}
|
||||
|
||||
private Template parseTemplate(String template) throws IOException {
|
||||
try (XContentParser parser = XContentFactory.xContent(template).createParser(template)) {
|
||||
return TemplateQueryBuilder.parse(parser, ParseFieldMatcher.EMPTY, "params", "template");
|
||||
}
|
||||
}
|
||||
|
||||
// Relates to #6318
|
||||
public void testSearchRequestFail() throws Exception {
|
||||
String query = "{ \"query\": {\"match_all\": {}}, \"size\" : \"{{my_size}}\" }";
|
||||
|
|
|
@ -18,31 +18,31 @@
|
|||
|
||||
- do:
|
||||
search:
|
||||
body: { "query": { "template": { "query": { "term": { "text": { "value": "{{template}}" } } }, "params": { "template": "value1" } } } }
|
||||
body: { "query": { "template": { "inline": { "term": { "text": { "value": "{{template}}" } } }, "params": { "template": "value1" } } } }
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query": { "template": { "query": {"match_{{template}}": {}}, "params" : { "template" : "all" } } } }
|
||||
body: { "query": { "template": { "inline": {"match_{{template}}": {}}, "params" : { "template" : "all" } } } }
|
||||
|
||||
- match: { hits.total: 2 }
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query": { "template": { "query": "{ \"term\": { \"text\": { \"value\": \"{{template}}\" } } }", "params": { "template": "value1" } } } }
|
||||
body: { "query": { "template": { "inline": "{ \"term\": { \"text\": { \"value\": \"{{template}}\" } } }", "params": { "template": "value1" } } } }
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query": { "template": { "query": "{\"match_{{template}}\": {}}", "params" : { "template" : "all" } } } }
|
||||
body: { "query": { "template": { "inline": "{\"match_{{template}}\": {}}", "params" : { "template" : "all" } } } }
|
||||
|
||||
- match: { hits.total: 2 }
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query": { "template": { "query": "{\"query_string\": { \"query\" : \"{{query}}\" }}", "params" : { "query" : "text:\"value2 value3\"" } } } }
|
||||
body: { "query": { "template": { "inline": "{\"query_string\": { \"query\" : \"{{query}}\" }}", "params" : { "query" : "text:\"value2 value3\"" } } } }
|
||||
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
|
|
@ -28,6 +28,6 @@
|
|||
msearch:
|
||||
body:
|
||||
- index: test_1
|
||||
- query: { "template": { "query": { "term": { "foo": { "value": "{{template}}" } } }, "params": { "template": "bar" } } }
|
||||
- query: { "template": { "inline": { "term": { "foo": { "value": "{{template}}" } } }, "params": { "template": "bar" } } }
|
||||
- match: { responses.0.hits.total: 1 }
|
||||
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
index: test_1
|
||||
type: test
|
||||
id: 1
|
||||
script: "1"
|
||||
body:
|
||||
lang: painless
|
||||
script: "ctx._source.foo = params.bar"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
lang: painless
|
||||
inline: "ctx._source.foo = params.bar"
|
||||
params: { bar: 'xxx' }
|
||||
|
||||
- match: { _index: test_1 }
|
||||
- match: { _type: test }
|
||||
|
@ -40,8 +40,10 @@
|
|||
index: test_1
|
||||
type: test
|
||||
id: 1
|
||||
lang: painless
|
||||
script: "ctx._source.foo = 'yyy'"
|
||||
body:
|
||||
script:
|
||||
lang: painless
|
||||
inline: "ctx._source.foo = 'yyy'"
|
||||
|
||||
- match: { _index: test_1 }
|
||||
- match: { _type: test }
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
|
||||
- do:
|
||||
|
@ -27,9 +28,10 @@
|
|||
type: test
|
||||
id: 1
|
||||
body:
|
||||
script: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
|
||||
- do:
|
||||
|
@ -46,9 +48,10 @@
|
|||
type: test
|
||||
id: 2
|
||||
body:
|
||||
script: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
script:
|
||||
inline: "ctx._source.foo = params.bar"
|
||||
lang: "painless"
|
||||
params: { bar: 'xxx' }
|
||||
upsert: { foo: baz }
|
||||
scripted_upsert: true
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
index: source
|
||||
query:
|
||||
script:
|
||||
lang: painless
|
||||
script: throw new IllegalArgumentException("Cats!")
|
||||
script:
|
||||
lang: painless
|
||||
inline: throw new IllegalArgumentException("Cats!")
|
||||
dest:
|
||||
index: dest
|
||||
- match: {created: 0}
|
||||
|
|
|
@ -16,8 +16,9 @@
|
|||
body:
|
||||
query:
|
||||
script:
|
||||
lang: painless
|
||||
script: throw new IllegalArgumentException("Cats!")
|
||||
script:
|
||||
lang: painless
|
||||
inline: throw new IllegalArgumentException("Cats!")
|
||||
- match: {updated: 0}
|
||||
- match: {version_conflicts: 0}
|
||||
- match: {batches: 0}
|
||||
|
|
|
@ -53,16 +53,6 @@
|
|||
"type": "string",
|
||||
"description": "Specific routing value"
|
||||
},
|
||||
"script": {
|
||||
"description": "The URL-encoded script definition (instead of using request body)"
|
||||
},
|
||||
"script_id": {
|
||||
"description": "The id of a stored script"
|
||||
},
|
||||
"scripted_upsert": {
|
||||
"type": "boolean",
|
||||
"description": "True if the script referenced in script or script_id should be called to perform inserts - defaults to false"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "time",
|
||||
"description": "Explicit operation timeout"
|
||||
|
|
Loading…
Reference in New Issue