org.elasticsearch.action.update.UpdateRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* 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.action.update;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.DocumentRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.replication.ReplicationRequest;
import org.elasticsearch.action.support.single.instance.InstanceShardOperationRequest;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
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.ScriptType;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
*/
public class UpdateRequest extends InstanceShardOperationRequest
implements DocumentRequest, WriteRequest {
private static final DeprecationLogger DEPRECATION_LOGGER =
new DeprecationLogger(Loggers.getLogger(UpdateRequest.class));
private String type;
private String id;
@Nullable
private String routing;
@Nullable
private String parent;
@Nullable
Script script;
private String[] fields;
private FetchSourceContext fetchSourceContext;
private long version = Versions.MATCH_ANY;
private VersionType versionType = VersionType.INTERNAL;
private int retryOnConflict = 0;
private RefreshPolicy refreshPolicy = RefreshPolicy.NONE;
private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT;
private IndexRequest upsertRequest;
private boolean scriptedUpsert = false;
private boolean docAsUpsert = false;
private boolean detectNoop = true;
private static DeprecationLogger deprecationLogger = new DeprecationLogger(Loggers.getLogger(UpdateRequest.class));
@Nullable
private IndexRequest doc;
public UpdateRequest() {
}
public UpdateRequest(String index, String type, String id) {
super(index);
this.type = type;
this.id = id;
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = super.validate();
if (type == null) {
validationException = addValidationError("type is missing", validationException);
}
if (id == null) {
validationException = addValidationError("id is missing", validationException);
}
if (!(versionType == VersionType.INTERNAL || versionType == VersionType.FORCE)) {
validationException = addValidationError("version type [" + versionType + "] is not supported by the update API", validationException);
} else {
if (version != Versions.MATCH_ANY && retryOnConflict > 0) {
validationException = addValidationError("can't provide both retry_on_conflict and a specific version", validationException);
}
if (!versionType.validateVersionForWrites(version)) {
validationException = addValidationError("illegal version value [" + version + "] for version type [" + versionType.name() + "]", validationException);
}
}
if (script == null && doc == null) {
validationException = addValidationError("script or doc is missing", validationException);
}
if (script != null && doc != null) {
validationException = addValidationError("can't provide both script and doc", validationException);
}
if (doc == null && docAsUpsert) {
validationException = addValidationError("doc must be specified if doc_as_upsert is enabled", validationException);
}
if (versionType == VersionType.FORCE) {
deprecationLogger.deprecated("version type FORCE is deprecated and will be removed in the next major version");
}
return validationException;
}
/**
* The type of the indexed document.
*/
@Override
public String type() {
return type;
}
/**
* Sets the type of the indexed document.
*/
public UpdateRequest type(String type) {
this.type = type;
return this;
}
/**
* The id of the indexed document.
*/
@Override
public String id() {
return id;
}
/**
* Sets the id of the indexed document.
*/
public UpdateRequest id(String id) {
this.id = id;
return this;
}
/**
* Controls the shard routing of the request. Using this value to hash the shard
* and not the id.
*/
@Override
public UpdateRequest routing(String routing) {
if (routing != null && routing.length() == 0) {
this.routing = null;
} else {
this.routing = routing;
}
return this;
}
/**
* Controls the shard routing of the request. Using this value to hash the shard
* and not the id.
*/
@Override
public String routing() {
return this.routing;
}
/**
* The parent id is used for the upsert request.
*/
public UpdateRequest parent(String parent) {
this.parent = parent;
return this;
}
public String parent() {
return parent;
}
public ShardId getShardId() {
return this.shardId;
}
public Script script() {
return this.script;
}
/**
* The script to execute. Note, make sure not to send different script each times and instead
* use script params if possible with the same (automatically compiled) script.
*/
public UpdateRequest script(Script script) {
this.script = script;
return this;
}
/**
* @deprecated Use {@link #script()} instead
*/
@Deprecated
public String scriptString() {
return this.script == null ? null : this.script.getIdOrCode();
}
/**
* @deprecated Use {@link #script()} instead
*/
@Deprecated
public ScriptType scriptType() {
return this.script == null ? null : this.script.getType();
}
/**
* @deprecated Use {@link #script()} instead
*/
@Deprecated
public Map scriptParams() {
return this.script == null ? null : this.script.getParams();
}
/**
* The script to execute. Note, make sure not to send different script each
* times and instead use script params if possible with the same
* (automatically compiled) script.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest script(String script, ScriptType scriptType) {
updateOrCreateScript(script, scriptType, null, null);
return this;
}
/**
* The script to execute. Note, make sure not to send different script each
* times and instead use script params if possible with the same
* (automatically compiled) script.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest script(String script) {
updateOrCreateScript(script, ScriptType.INLINE, null, null);
return this;
}
/**
* The language of the script to execute.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest scriptLang(String scriptLang) {
updateOrCreateScript(null, null, scriptLang, null);
return this;
}
/**
* @deprecated Use {@link #script()} instead
*/
@Deprecated
public String scriptLang() {
return script == null ? null : script.getLang();
}
/**
* Add a script parameter.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest addScriptParam(String name, Object value) {
Script script = script();
if (script == null) {
HashMap scriptParams = new HashMap<>();
scriptParams.put(name, value);
updateOrCreateScript(null, null, null, scriptParams);
} else {
Map scriptParams = script.getParams();
if (scriptParams == null) {
scriptParams = new HashMap<>();
scriptParams.put(name, value);
updateOrCreateScript(null, null, null, scriptParams);
} else {
scriptParams.put(name, value);
}
}
return this;
}
/**
* Sets the script parameters to use with the script.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest scriptParams(Map scriptParams) {
updateOrCreateScript(null, null, null, scriptParams);
return this;
}
private void updateOrCreateScript(String scriptContent, ScriptType type, String lang, Map params) {
Script script = script();
if (script == null) {
script = new Script(type == null ? ScriptType.INLINE : type, lang, scriptContent == null ? "" : scriptContent, params);
} else {
String newScriptContent = scriptContent == null ? script.getIdOrCode() : scriptContent;
ScriptType newScriptType = type == null ? script.getType() : type;
String newScriptLang = lang == null ? script.getLang() : lang;
Map newScriptParams = params == null ? script.getParams() : params;
script = new Script(newScriptType, newScriptLang, newScriptContent, newScriptParams);
}
script(script);
}
/**
* The script to execute. Note, make sure not to send different script each
* times and instead use script params if possible with the same
* (automatically compiled) script.
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest script(String script, ScriptType scriptType, @Nullable Map scriptParams) {
this.script = new Script(scriptType, Script.DEFAULT_SCRIPT_LANG, script, scriptParams);
return this;
}
/**
* The script to execute. Note, make sure not to send different script each
* times and instead use script params if possible with the same
* (automatically compiled) script.
*
* @param script
* The script to execute
* @param scriptLang
* The script language
* @param scriptType
* The script type
* @param scriptParams
* The script parameters
*
* @deprecated Use {@link #script(Script)} instead
*/
@Deprecated
public UpdateRequest script(String script, @Nullable String scriptLang, ScriptType scriptType,
@Nullable Map scriptParams) {
this.script = new Script(scriptType, scriptLang, script, scriptParams);
return this;
}
/**
* Explicitly specify the fields that will be returned. By default, nothing is returned.
* @deprecated Use {@link UpdateRequest#fetchSource(String[], String[])} instead
*/
@Deprecated
public UpdateRequest fields(String... fields) {
this.fields = fields;
return this;
}
/**
* Indicate that _source should be returned with every hit, with an
* "include" and/or "exclude" set which can include simple wildcard
* elements.
*
* @param include
* An optional include (optionally wildcarded) pattern to filter
* the returned _source
* @param exclude
* An optional exclude (optionally wildcarded) pattern to filter
* the returned _source
*/
public UpdateRequest fetchSource(@Nullable String include, @Nullable String exclude) {
FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), new String[] {include}, new String[]{exclude});
return this;
}
/**
* Indicate that _source should be returned, with an
* "include" and/or "exclude" set which can include simple wildcard
* elements.
*
* @param includes
* An optional list of include (optionally wildcarded) pattern to
* filter the returned _source
* @param excludes
* An optional list of exclude (optionally wildcarded) pattern to
* filter the returned _source
*/
public UpdateRequest fetchSource(@Nullable String[] includes, @Nullable String[] excludes) {
FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), includes, excludes);
return this;
}
/**
* Indicates whether the response should contain the updated _source.
*/
public UpdateRequest fetchSource(boolean fetchSource) {
FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
this.fetchSourceContext = new FetchSourceContext(fetchSource, context.includes(), context.excludes());
return this;
}
/**
* Explicitely set the fetch source context for this request
*/
public UpdateRequest fetchSource(FetchSourceContext context) {
this.fetchSourceContext = context;
return this;
}
/**
* Get the fields to be returned.
* @deprecated Use {@link UpdateRequest#fetchSource()} instead
*/
@Deprecated
public String[] fields() {
return fields;
}
/**
* Gets the {@link FetchSourceContext} which defines how the _source should
* be fetched.
*/
public FetchSourceContext fetchSource() {
return fetchSourceContext;
}
/**
* Sets the number of retries of a version conflict occurs because the document was updated between
* getting it and updating it. Defaults to 0.
*/
public UpdateRequest retryOnConflict(int retryOnConflict) {
this.retryOnConflict = retryOnConflict;
return this;
}
public int retryOnConflict() {
return this.retryOnConflict;
}
/**
* Sets the version, which will cause the index operation to only be performed if a matching
* version exists and no changes happened on the doc since then.
*/
public UpdateRequest version(long version) {
this.version = version;
return this;
}
public long version() {
return this.version;
}
/**
* Sets the versioning type. Defaults to {@link VersionType#INTERNAL}.
*/
public UpdateRequest versionType(VersionType versionType) {
this.versionType = versionType;
return this;
}
public VersionType versionType() {
return this.versionType;
}
@Override
public UpdateRequest setRefreshPolicy(RefreshPolicy refreshPolicy) {
this.refreshPolicy = refreshPolicy;
return this;
}
@Override
public RefreshPolicy getRefreshPolicy() {
return refreshPolicy;
}
public ActiveShardCount waitForActiveShards() {
return this.waitForActiveShards;
}
/**
* Sets the number of shard copies that must be active before proceeding with the write.
* See {@link ReplicationRequest#waitForActiveShards(ActiveShardCount)} for details.
*/
public UpdateRequest waitForActiveShards(ActiveShardCount waitForActiveShards) {
this.waitForActiveShards = waitForActiveShards;
return this;
}
/**
* A shortcut for {@link #waitForActiveShards(ActiveShardCount)} where the numerical
* shard count is passed in, instead of having to first call {@link ActiveShardCount#from(int)}
* to get the ActiveShardCount.
*/
public UpdateRequest waitForActiveShards(final int waitForActiveShards) {
return waitForActiveShards(ActiveShardCount.from(waitForActiveShards));
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(IndexRequest doc) {
this.doc = doc;
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(XContentBuilder source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(Map source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(Map source, XContentType contentType) {
safeDoc().source(source, contentType);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(String source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(byte[] source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(byte[] source, int offset, int length) {
safeDoc().source(source, offset, length);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified, the doc provided
* is a field and value pairs.
*/
public UpdateRequest doc(Object... source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
public UpdateRequest doc(String field, Object value) {
safeDoc().source(field, value);
return this;
}
public IndexRequest doc() {
return this.doc;
}
private IndexRequest safeDoc() {
if (doc == null) {
doc = new IndexRequest();
}
return doc;
}
/**
* Sets the index request to be used if the document does not exists. Otherwise, a {@link org.elasticsearch.index.engine.DocumentMissingException}
* is thrown.
*/
public UpdateRequest upsert(IndexRequest upsertRequest) {
this.upsertRequest = upsertRequest;
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(XContentBuilder source) {
safeUpsertRequest().source(source);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(Map source) {
safeUpsertRequest().source(source);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(Map source, XContentType contentType) {
safeUpsertRequest().source(source, contentType);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(String source) {
safeUpsertRequest().source(source);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(byte[] source) {
safeUpsertRequest().source(source);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequest upsert(byte[] source, int offset, int length) {
safeUpsertRequest().source(source, offset, length);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists. The doc
* includes field and value pairs.
*/
public UpdateRequest upsert(Object... source) {
safeUpsertRequest().source(source);
return this;
}
public IndexRequest upsertRequest() {
return this.upsertRequest;
}
private IndexRequest safeUpsertRequest() {
if (upsertRequest == null) {
upsertRequest = new IndexRequest();
}
return upsertRequest;
}
public UpdateRequest fromXContent(XContentBuilder source) throws Exception {
return fromXContent(source.bytes());
}
public UpdateRequest fromXContent(byte[] source) throws Exception {
return fromXContent(source, 0, source.length);
}
public UpdateRequest fromXContent(byte[] source, int offset, int length) throws Exception {
return fromXContent(new BytesArray(source, offset, length));
}
/**
* Should this update attempt to detect if it is a noop? Defaults to true.
* @return this for chaining
*/
public UpdateRequest detectNoop(boolean detectNoop) {
this.detectNoop = detectNoop;
return this;
}
/**
* Should this update attempt to detect if it is a noop? Defaults to true.
*/
public boolean detectNoop() {
return detectNoop;
}
public UpdateRequest fromXContent(BytesReference source) throws IOException {
Script script = null;
try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) {
XContentParser.Token token = parser.nextToken();
if (token == null) {
return this;
}
String currentFieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if ("script".equals(currentFieldName)) {
script = Script.parse(parser, ParseFieldMatcher.EMPTY);
} else if ("scripted_upsert".equals(currentFieldName)) {
scriptedUpsert = parser.booleanValue();
} else if ("upsert".equals(currentFieldName)) {
XContentType xContentType = XContentFactory.xContentType(source);
XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
builder.copyCurrentStructure(parser);
safeUpsertRequest().source(builder);
} else if ("doc".equals(currentFieldName)) {
XContentType xContentType = XContentFactory.xContentType(source);
XContentBuilder docBuilder = XContentFactory.contentBuilder(xContentType);
docBuilder.copyCurrentStructure(parser);
safeDoc().source(docBuilder);
} else if ("doc_as_upsert".equals(currentFieldName)) {
docAsUpsert(parser.booleanValue());
} else if ("detect_noop".equals(currentFieldName)) {
detectNoop(parser.booleanValue());
} else if ("fields".equals(currentFieldName)) {
List