UpdateRequest.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. /*
  2. * Licensed to Elasticsearch under one or more contributor
  3. * license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright
  5. * ownership. Elasticsearch licenses this file to you under
  6. * the Apache License, Version 2.0 (the "License"); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.elasticsearch.action.update;
  20. import org.elasticsearch.Version;
  21. import org.elasticsearch.action.ActionRequestValidationException;
  22. import org.elasticsearch.action.DocWriteRequest;
  23. import org.elasticsearch.action.index.IndexRequest;
  24. import org.elasticsearch.action.support.ActiveShardCount;
  25. import org.elasticsearch.action.support.WriteRequest;
  26. import org.elasticsearch.action.support.replication.ReplicationRequest;
  27. import org.elasticsearch.action.support.single.instance.InstanceShardOperationRequest;
  28. import org.elasticsearch.common.Nullable;
  29. import org.elasticsearch.common.ParseField;
  30. import org.elasticsearch.common.Strings;
  31. import org.elasticsearch.common.io.stream.StreamInput;
  32. import org.elasticsearch.common.io.stream.StreamOutput;
  33. import org.elasticsearch.common.lucene.uid.Versions;
  34. import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
  35. import org.elasticsearch.common.xcontent.NamedXContentRegistry;
  36. import org.elasticsearch.common.xcontent.ObjectParser;
  37. import org.elasticsearch.common.xcontent.ToXContentObject;
  38. import org.elasticsearch.common.xcontent.XContentBuilder;
  39. import org.elasticsearch.common.xcontent.XContentFactory;
  40. import org.elasticsearch.common.xcontent.XContentHelper;
  41. import org.elasticsearch.common.xcontent.XContentParser;
  42. import org.elasticsearch.common.xcontent.XContentType;
  43. import org.elasticsearch.index.VersionType;
  44. import org.elasticsearch.index.mapper.MapperService;
  45. import org.elasticsearch.index.shard.ShardId;
  46. import org.elasticsearch.script.Script;
  47. import org.elasticsearch.script.ScriptType;
  48. import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
  49. import java.io.IOException;
  50. import java.util.HashMap;
  51. import java.util.Map;
  52. import static org.elasticsearch.action.ValidateActions.addValidationError;
  53. public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
  54. implements DocWriteRequest<UpdateRequest>, WriteRequest<UpdateRequest>, ToXContentObject {
  55. private static ObjectParser<UpdateRequest, Void> PARSER;
  56. private static final ParseField SCRIPT_FIELD = new ParseField("script");
  57. private static final ParseField SCRIPTED_UPSERT_FIELD = new ParseField("scripted_upsert");
  58. private static final ParseField UPSERT_FIELD = new ParseField("upsert");
  59. private static final ParseField DOC_FIELD = new ParseField("doc");
  60. private static final ParseField DOC_AS_UPSERT_FIELD = new ParseField("doc_as_upsert");
  61. private static final ParseField DETECT_NOOP_FIELD = new ParseField("detect_noop");
  62. private static final ParseField SOURCE_FIELD = new ParseField("_source");
  63. static {
  64. PARSER = new ObjectParser<>(UpdateRequest.class.getSimpleName());
  65. PARSER.declareField((request, script) -> request.script = script,
  66. (parser, context) -> Script.parse(parser), SCRIPT_FIELD, ObjectParser.ValueType.OBJECT_OR_STRING);
  67. PARSER.declareBoolean(UpdateRequest::scriptedUpsert, SCRIPTED_UPSERT_FIELD);
  68. PARSER.declareObject((request, builder) -> request.safeUpsertRequest().source(builder),
  69. (parser, context) -> {
  70. XContentBuilder builder = XContentFactory.contentBuilder(parser.contentType());
  71. builder.copyCurrentStructure(parser);
  72. return builder;
  73. }, UPSERT_FIELD);
  74. PARSER.declareObject((request, builder) -> request.safeDoc().source(builder),
  75. (parser, context) -> {
  76. XContentBuilder docBuilder = XContentFactory.contentBuilder(parser.contentType());
  77. docBuilder.copyCurrentStructure(parser);
  78. return docBuilder;
  79. }, DOC_FIELD);
  80. PARSER.declareBoolean(UpdateRequest::docAsUpsert, DOC_AS_UPSERT_FIELD);
  81. PARSER.declareBoolean(UpdateRequest::detectNoop, DETECT_NOOP_FIELD);
  82. PARSER.declareField(UpdateRequest::fetchSource,
  83. (parser, context) -> FetchSourceContext.fromXContent(parser), SOURCE_FIELD,
  84. ObjectParser.ValueType.OBJECT_ARRAY_BOOLEAN_OR_STRING);
  85. }
  86. // Set to null initially so we can know to override in bulk requests that have a default type.
  87. private String type;
  88. private String id;
  89. @Nullable
  90. private String routing;
  91. @Nullable
  92. Script script;
  93. private FetchSourceContext fetchSourceContext;
  94. private long version = Versions.MATCH_ANY;
  95. private VersionType versionType = VersionType.INTERNAL;
  96. private int retryOnConflict = 0;
  97. private RefreshPolicy refreshPolicy = RefreshPolicy.NONE;
  98. private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT;
  99. private IndexRequest upsertRequest;
  100. private boolean scriptedUpsert = false;
  101. private boolean docAsUpsert = false;
  102. private boolean detectNoop = true;
  103. @Nullable
  104. private IndexRequest doc;
  105. public UpdateRequest() {
  106. }
  107. public UpdateRequest(String index, String id) {
  108. super(index);
  109. this.id = id;
  110. }
  111. /**
  112. * @deprecated Types are in the process of being removed. Use {@link #UpdateRequest(String, String)} instead.
  113. */
  114. @Deprecated
  115. public UpdateRequest(String index, String type, String id) {
  116. super(index);
  117. this.type = type;
  118. this.id = id;
  119. }
  120. @Override
  121. public ActionRequestValidationException validate() {
  122. ActionRequestValidationException validationException = super.validate();
  123. if (version != Versions.MATCH_ANY && upsertRequest != null) {
  124. validationException = addValidationError("can't provide both upsert request and a version", validationException);
  125. }
  126. if(upsertRequest != null && upsertRequest.version() != Versions.MATCH_ANY) {
  127. validationException = addValidationError("can't provide version in upsert request", validationException);
  128. }
  129. if (Strings.isEmpty(type())) {
  130. validationException = addValidationError("type is missing", validationException);
  131. }
  132. if (Strings.isEmpty(id)) {
  133. validationException = addValidationError("id is missing", validationException);
  134. }
  135. if (versionType != VersionType.INTERNAL) {
  136. validationException = addValidationError("version type [" + versionType + "] is not supported by the update API",
  137. validationException);
  138. } else {
  139. if (version != Versions.MATCH_ANY && retryOnConflict > 0) {
  140. validationException = addValidationError("can't provide both retry_on_conflict and a specific version",
  141. validationException);
  142. }
  143. if (!versionType.validateVersionForWrites(version)) {
  144. validationException = addValidationError("illegal version value [" + version + "] for version type [" +
  145. versionType.name() + "]", validationException);
  146. }
  147. }
  148. if (script == null && doc == null) {
  149. validationException = addValidationError("script or doc is missing", validationException);
  150. }
  151. if (script != null && doc != null) {
  152. validationException = addValidationError("can't provide both script and doc", validationException);
  153. }
  154. if (doc == null && docAsUpsert) {
  155. validationException = addValidationError("doc must be specified if doc_as_upsert is enabled", validationException);
  156. }
  157. return validationException;
  158. }
  159. /**
  160. * The type of the indexed document.
  161. *
  162. * @deprecated Types are in the process of being removed.
  163. */
  164. @Deprecated
  165. @Override
  166. public String type() {
  167. if (type == null) {
  168. return MapperService.SINGLE_MAPPING_NAME;
  169. }
  170. return type;
  171. }
  172. /**
  173. * Sets the type of the indexed document.
  174. *
  175. * @deprecated Types are in the process of being removed.
  176. */
  177. @Deprecated
  178. public UpdateRequest type(String type) {
  179. this.type = type;
  180. return this;
  181. }
  182. /**
  183. * Set the default type supplied to a bulk
  184. * request if this individual request's type is null
  185. * or empty
  186. * @deprecated Types are in the process of being removed.
  187. */
  188. @Deprecated
  189. @Override
  190. public UpdateRequest defaultTypeIfNull(String defaultType) {
  191. if (Strings.isNullOrEmpty(type)) {
  192. type = defaultType;
  193. }
  194. return this;
  195. }
  196. /**
  197. * The id of the indexed document.
  198. */
  199. @Override
  200. public String id() {
  201. return id;
  202. }
  203. /**
  204. * Sets the id of the indexed document.
  205. */
  206. public UpdateRequest id(String id) {
  207. this.id = id;
  208. return this;
  209. }
  210. /**
  211. * Controls the shard routing of the request. Using this value to hash the shard
  212. * and not the id.
  213. */
  214. @Override
  215. public UpdateRequest routing(String routing) {
  216. if (routing != null && routing.length() == 0) {
  217. this.routing = null;
  218. } else {
  219. this.routing = routing;
  220. }
  221. return this;
  222. }
  223. /**
  224. * Controls the shard routing of the request. Using this value to hash the shard
  225. * and not the id.
  226. */
  227. @Override
  228. public String routing() {
  229. return this.routing;
  230. }
  231. public ShardId getShardId() {
  232. return this.shardId;
  233. }
  234. public Script script() {
  235. return this.script;
  236. }
  237. /**
  238. * The script to execute. Note, make sure not to send different script each times and instead
  239. * use script params if possible with the same (automatically compiled) script.
  240. */
  241. public UpdateRequest script(Script script) {
  242. this.script = script;
  243. return this;
  244. }
  245. /**
  246. * @deprecated Use {@link #script()} instead
  247. */
  248. @Deprecated
  249. public String scriptString() {
  250. return this.script == null ? null : this.script.getIdOrCode();
  251. }
  252. /**
  253. * @deprecated Use {@link #script()} instead
  254. */
  255. @Deprecated
  256. public ScriptType scriptType() {
  257. return this.script == null ? null : this.script.getType();
  258. }
  259. /**
  260. * @deprecated Use {@link #script()} instead
  261. */
  262. @Deprecated
  263. public Map<String, Object> scriptParams() {
  264. return this.script == null ? null : this.script.getParams();
  265. }
  266. /**
  267. * The script to execute. Note, make sure not to send different script each
  268. * times and instead use script params if possible with the same
  269. * (automatically compiled) script.
  270. *
  271. * @deprecated Use {@link #script(Script)} instead
  272. */
  273. @Deprecated
  274. public UpdateRequest script(String script, ScriptType scriptType) {
  275. updateOrCreateScript(script, scriptType, null, null);
  276. return this;
  277. }
  278. /**
  279. * The script to execute. Note, make sure not to send different script each
  280. * times and instead use script params if possible with the same
  281. * (automatically compiled) script.
  282. *
  283. * @deprecated Use {@link #script(Script)} instead
  284. */
  285. @Deprecated
  286. public UpdateRequest script(String script) {
  287. updateOrCreateScript(script, ScriptType.INLINE, null, null);
  288. return this;
  289. }
  290. /**
  291. * The language of the script to execute.
  292. *
  293. * @deprecated Use {@link #script(Script)} instead
  294. */
  295. @Deprecated
  296. public UpdateRequest scriptLang(String scriptLang) {
  297. updateOrCreateScript(null, null, scriptLang, null);
  298. return this;
  299. }
  300. /**
  301. * @deprecated Use {@link #script()} instead
  302. */
  303. @Deprecated
  304. public String scriptLang() {
  305. return script == null ? null : script.getLang();
  306. }
  307. /**
  308. * Add a script parameter.
  309. *
  310. * @deprecated Use {@link #script(Script)} instead
  311. */
  312. @Deprecated
  313. public UpdateRequest addScriptParam(String name, Object value) {
  314. Script script = script();
  315. if (script == null) {
  316. HashMap<String, Object> scriptParams = new HashMap<>();
  317. scriptParams.put(name, value);
  318. updateOrCreateScript(null, null, null, scriptParams);
  319. } else {
  320. Map<String, Object> scriptParams = script.getParams();
  321. if (scriptParams == null) {
  322. scriptParams = new HashMap<>();
  323. scriptParams.put(name, value);
  324. updateOrCreateScript(null, null, null, scriptParams);
  325. } else {
  326. scriptParams.put(name, value);
  327. }
  328. }
  329. return this;
  330. }
  331. /**
  332. * Sets the script parameters to use with the script.
  333. *
  334. * @deprecated Use {@link #script(Script)} instead
  335. */
  336. @Deprecated
  337. public UpdateRequest scriptParams(Map<String, Object> scriptParams) {
  338. updateOrCreateScript(null, null, null, scriptParams);
  339. return this;
  340. }
  341. private void updateOrCreateScript(String scriptContent, ScriptType type, String lang, Map<String, Object> params) {
  342. Script script = script();
  343. if (script == null) {
  344. script = new Script(type == null ? ScriptType.INLINE : type, lang, scriptContent == null ? "" : scriptContent, params);
  345. } else {
  346. String newScriptContent = scriptContent == null ? script.getIdOrCode() : scriptContent;
  347. ScriptType newScriptType = type == null ? script.getType() : type;
  348. String newScriptLang = lang == null ? script.getLang() : lang;
  349. Map<String, Object> newScriptParams = params == null ? script.getParams() : params;
  350. script = new Script(newScriptType, newScriptLang, newScriptContent, newScriptParams);
  351. }
  352. script(script);
  353. }
  354. /**
  355. * The script to execute. Note, make sure not to send different script each
  356. * times and instead use script params if possible with the same
  357. * (automatically compiled) script.
  358. *
  359. * @deprecated Use {@link #script(Script)} instead
  360. */
  361. @Deprecated
  362. public UpdateRequest script(String script, ScriptType scriptType, @Nullable Map<String, Object> scriptParams) {
  363. this.script = new Script(scriptType, Script.DEFAULT_SCRIPT_LANG, script, scriptParams);
  364. return this;
  365. }
  366. /**
  367. * The script to execute. Note, make sure not to send different script each
  368. * times and instead use script params if possible with the same
  369. * (automatically compiled) script.
  370. *
  371. * @param script
  372. * The script to execute
  373. * @param scriptLang
  374. * The script language
  375. * @param scriptType
  376. * The script type
  377. * @param scriptParams
  378. * The script parameters
  379. *
  380. * @deprecated Use {@link #script(Script)} instead
  381. */
  382. @Deprecated
  383. public UpdateRequest script(String script, @Nullable String scriptLang, ScriptType scriptType,
  384. @Nullable Map<String, Object> scriptParams) {
  385. this.script = new Script(scriptType, scriptLang, script, scriptParams);
  386. return this;
  387. }
  388. /**
  389. * Indicate that _source should be returned with every hit, with an
  390. * "include" and/or "exclude" set which can include simple wildcard
  391. * elements.
  392. *
  393. * @param include
  394. * An optional include (optionally wildcarded) pattern to filter
  395. * the returned _source
  396. * @param exclude
  397. * An optional exclude (optionally wildcarded) pattern to filter
  398. * the returned _source
  399. */
  400. public UpdateRequest fetchSource(@Nullable String include, @Nullable String exclude) {
  401. FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
  402. String[] includes = include == null ? Strings.EMPTY_ARRAY : new String[]{include};
  403. String[] excludes = exclude == null ? Strings.EMPTY_ARRAY : new String[]{exclude};
  404. this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), includes, excludes);
  405. return this;
  406. }
  407. /**
  408. * Indicate that _source should be returned, with an
  409. * "include" and/or "exclude" set which can include simple wildcard
  410. * elements.
  411. *
  412. * @param includes
  413. * An optional list of include (optionally wildcarded) pattern to
  414. * filter the returned _source
  415. * @param excludes
  416. * An optional list of exclude (optionally wildcarded) pattern to
  417. * filter the returned _source
  418. */
  419. public UpdateRequest fetchSource(@Nullable String[] includes, @Nullable String[] excludes) {
  420. FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
  421. this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), includes, excludes);
  422. return this;
  423. }
  424. /**
  425. * Indicates whether the response should contain the updated _source.
  426. */
  427. public UpdateRequest fetchSource(boolean fetchSource) {
  428. FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;
  429. this.fetchSourceContext = new FetchSourceContext(fetchSource, context.includes(), context.excludes());
  430. return this;
  431. }
  432. /**
  433. * Explicitly set the fetch source context for this request
  434. */
  435. public UpdateRequest fetchSource(FetchSourceContext context) {
  436. this.fetchSourceContext = context;
  437. return this;
  438. }
  439. /**
  440. * Gets the {@link FetchSourceContext} which defines how the _source should
  441. * be fetched.
  442. */
  443. public FetchSourceContext fetchSource() {
  444. return fetchSourceContext;
  445. }
  446. /**
  447. * Sets the number of retries of a version conflict occurs because the document was updated between
  448. * getting it and updating it. Defaults to 0.
  449. */
  450. public UpdateRequest retryOnConflict(int retryOnConflict) {
  451. this.retryOnConflict = retryOnConflict;
  452. return this;
  453. }
  454. public int retryOnConflict() {
  455. return this.retryOnConflict;
  456. }
  457. @Override
  458. public UpdateRequest version(long version) {
  459. this.version = version;
  460. return this;
  461. }
  462. @Override
  463. public long version() {
  464. return this.version;
  465. }
  466. @Override
  467. public UpdateRequest versionType(VersionType versionType) {
  468. this.versionType = versionType;
  469. return this;
  470. }
  471. @Override
  472. public VersionType versionType() {
  473. return this.versionType;
  474. }
  475. @Override
  476. public OpType opType() {
  477. return OpType.UPDATE;
  478. }
  479. @Override
  480. public UpdateRequest setRefreshPolicy(RefreshPolicy refreshPolicy) {
  481. this.refreshPolicy = refreshPolicy;
  482. return this;
  483. }
  484. @Override
  485. public RefreshPolicy getRefreshPolicy() {
  486. return refreshPolicy;
  487. }
  488. public ActiveShardCount waitForActiveShards() {
  489. return this.waitForActiveShards;
  490. }
  491. /**
  492. * Sets the number of shard copies that must be active before proceeding with the write.
  493. * See {@link ReplicationRequest#waitForActiveShards(ActiveShardCount)} for details.
  494. */
  495. public UpdateRequest waitForActiveShards(ActiveShardCount waitForActiveShards) {
  496. this.waitForActiveShards = waitForActiveShards;
  497. return this;
  498. }
  499. /**
  500. * A shortcut for {@link #waitForActiveShards(ActiveShardCount)} where the numerical
  501. * shard count is passed in, instead of having to first call {@link ActiveShardCount#from(int)}
  502. * to get the ActiveShardCount.
  503. */
  504. public UpdateRequest waitForActiveShards(final int waitForActiveShards) {
  505. return waitForActiveShards(ActiveShardCount.from(waitForActiveShards));
  506. }
  507. /**
  508. * Sets the doc to use for updates when a script is not specified.
  509. */
  510. public UpdateRequest doc(IndexRequest doc) {
  511. this.doc = doc;
  512. return this;
  513. }
  514. /**
  515. * Sets the doc to use for updates when a script is not specified.
  516. */
  517. public UpdateRequest doc(XContentBuilder source) {
  518. safeDoc().source(source);
  519. return this;
  520. }
  521. /**
  522. * Sets the doc to use for updates when a script is not specified.
  523. */
  524. public UpdateRequest doc(Map<String, Object> source) {
  525. safeDoc().source(source);
  526. return this;
  527. }
  528. /**
  529. * Sets the doc to use for updates when a script is not specified.
  530. */
  531. public UpdateRequest doc(Map<String, Object> source, XContentType contentType) {
  532. safeDoc().source(source, contentType);
  533. return this;
  534. }
  535. /**
  536. * Sets the doc to use for updates when a script is not specified.
  537. */
  538. public UpdateRequest doc(String source, XContentType xContentType) {
  539. safeDoc().source(source, xContentType);
  540. return this;
  541. }
  542. /**
  543. * Sets the doc to use for updates when a script is not specified.
  544. */
  545. public UpdateRequest doc(byte[] source, XContentType xContentType) {
  546. safeDoc().source(source, xContentType);
  547. return this;
  548. }
  549. /**
  550. * Sets the doc to use for updates when a script is not specified.
  551. */
  552. public UpdateRequest doc(byte[] source, int offset, int length, XContentType xContentType) {
  553. safeDoc().source(source, offset, length, xContentType);
  554. return this;
  555. }
  556. /**
  557. * Sets the doc to use for updates when a script is not specified, the doc provided
  558. * is a field and value pairs.
  559. */
  560. public UpdateRequest doc(Object... source) {
  561. safeDoc().source(source);
  562. return this;
  563. }
  564. /**
  565. * Sets the doc to use for updates when a script is not specified, the doc provided
  566. * is a field and value pairs.
  567. */
  568. public UpdateRequest doc(XContentType xContentType, Object... source) {
  569. safeDoc().source(xContentType, source);
  570. return this;
  571. }
  572. public IndexRequest doc() {
  573. return this.doc;
  574. }
  575. private IndexRequest safeDoc() {
  576. if (doc == null) {
  577. doc = new IndexRequest();
  578. }
  579. return doc;
  580. }
  581. /**
  582. * Sets the index request to be used if the document does not exists. Otherwise, a
  583. * {@link org.elasticsearch.index.engine.DocumentMissingException} is thrown.
  584. */
  585. public UpdateRequest upsert(IndexRequest upsertRequest) {
  586. this.upsertRequest = upsertRequest;
  587. return this;
  588. }
  589. /**
  590. * Sets the doc source of the update request to be used when the document does not exists.
  591. */
  592. public UpdateRequest upsert(XContentBuilder source) {
  593. safeUpsertRequest().source(source);
  594. return this;
  595. }
  596. /**
  597. * Sets the doc source of the update request to be used when the document does not exists.
  598. */
  599. public UpdateRequest upsert(Map<String, Object> source) {
  600. safeUpsertRequest().source(source);
  601. return this;
  602. }
  603. /**
  604. * Sets the doc source of the update request to be used when the document does not exists.
  605. */
  606. public UpdateRequest upsert(Map<String, Object> source, XContentType contentType) {
  607. safeUpsertRequest().source(source, contentType);
  608. return this;
  609. }
  610. /**
  611. * Sets the doc source of the update request to be used when the document does not exists.
  612. */
  613. public UpdateRequest upsert(String source, XContentType xContentType) {
  614. safeUpsertRequest().source(source, xContentType);
  615. return this;
  616. }
  617. /**
  618. * Sets the doc source of the update request to be used when the document does not exists.
  619. */
  620. public UpdateRequest upsert(byte[] source, XContentType xContentType) {
  621. safeUpsertRequest().source(source, xContentType);
  622. return this;
  623. }
  624. /**
  625. * Sets the doc source of the update request to be used when the document does not exists.
  626. */
  627. public UpdateRequest upsert(byte[] source, int offset, int length, XContentType xContentType) {
  628. safeUpsertRequest().source(source, offset, length, xContentType);
  629. return this;
  630. }
  631. /**
  632. * Sets the doc source of the update request to be used when the document does not exists. The doc
  633. * includes field and value pairs.
  634. */
  635. public UpdateRequest upsert(Object... source) {
  636. safeUpsertRequest().source(source);
  637. return this;
  638. }
  639. /**
  640. * Sets the doc source of the update request to be used when the document does not exists. The doc
  641. * includes field and value pairs.
  642. */
  643. public UpdateRequest upsert(XContentType xContentType, Object... source) {
  644. safeUpsertRequest().source(xContentType, source);
  645. return this;
  646. }
  647. public IndexRequest upsertRequest() {
  648. return this.upsertRequest;
  649. }
  650. private IndexRequest safeUpsertRequest() {
  651. if (upsertRequest == null) {
  652. upsertRequest = new IndexRequest();
  653. }
  654. return upsertRequest;
  655. }
  656. /**
  657. * Should this update attempt to detect if it is a noop? Defaults to true.
  658. * @return this for chaining
  659. */
  660. public UpdateRequest detectNoop(boolean detectNoop) {
  661. this.detectNoop = detectNoop;
  662. return this;
  663. }
  664. /**
  665. * Should this update attempt to detect if it is a noop? Defaults to true.
  666. */
  667. public boolean detectNoop() {
  668. return detectNoop;
  669. }
  670. public UpdateRequest fromXContent(XContentParser parser) throws IOException {
  671. return PARSER.parse(parser, this, null);
  672. }
  673. public boolean docAsUpsert() {
  674. return this.docAsUpsert;
  675. }
  676. public UpdateRequest docAsUpsert(boolean shouldUpsertDoc) {
  677. this.docAsUpsert = shouldUpsertDoc;
  678. return this;
  679. }
  680. public boolean scriptedUpsert(){
  681. return this.scriptedUpsert;
  682. }
  683. public UpdateRequest scriptedUpsert(boolean scriptedUpsert) {
  684. this.scriptedUpsert = scriptedUpsert;
  685. return this;
  686. }
  687. @Override
  688. public void readFrom(StreamInput in) throws IOException {
  689. super.readFrom(in);
  690. waitForActiveShards = ActiveShardCount.readFrom(in);
  691. type = in.readString();
  692. id = in.readString();
  693. routing = in.readOptionalString();
  694. if (in.getVersion().before(Version.V_7_0_0)) {
  695. in.readOptionalString(); // _parent
  696. }
  697. if (in.readBoolean()) {
  698. script = new Script(in);
  699. }
  700. retryOnConflict = in.readVInt();
  701. refreshPolicy = RefreshPolicy.readFrom(in);
  702. if (in.readBoolean()) {
  703. doc = new IndexRequest();
  704. doc.readFrom(in);
  705. }
  706. if (in.getVersion().before(Version.V_7_0_0)) {
  707. String[] fields = in.readOptionalStringArray();
  708. if (fields != null) {
  709. throw new IllegalArgumentException("[fields] is no longer supported");
  710. }
  711. }
  712. fetchSourceContext = in.readOptionalWriteable(FetchSourceContext::new);
  713. if (in.readBoolean()) {
  714. upsertRequest = new IndexRequest();
  715. upsertRequest.readFrom(in);
  716. }
  717. docAsUpsert = in.readBoolean();
  718. version = in.readLong();
  719. versionType = VersionType.fromValue(in.readByte());
  720. detectNoop = in.readBoolean();
  721. scriptedUpsert = in.readBoolean();
  722. }
  723. @Override
  724. public void writeTo(StreamOutput out) throws IOException {
  725. super.writeTo(out);
  726. waitForActiveShards.writeTo(out);
  727. // A 7.x request allows null types but if deserialized in a 6.x node will cause nullpointer exceptions.
  728. // So we use the type accessor method here to make the type non-null (will default it to "_doc").
  729. out.writeString(type());
  730. out.writeString(id);
  731. out.writeOptionalString(routing);
  732. if (out.getVersion().before(Version.V_7_0_0)) {
  733. out.writeOptionalString(null); // _parent
  734. }
  735. boolean hasScript = script != null;
  736. out.writeBoolean(hasScript);
  737. if (hasScript) {
  738. script.writeTo(out);
  739. }
  740. out.writeVInt(retryOnConflict);
  741. refreshPolicy.writeTo(out);
  742. if (doc == null) {
  743. out.writeBoolean(false);
  744. } else {
  745. out.writeBoolean(true);
  746. // make sure the basics are set
  747. doc.index(index);
  748. doc.type(type);
  749. doc.id(id);
  750. doc.writeTo(out);
  751. }
  752. if (out.getVersion().before(Version.V_7_0_0)) {
  753. out.writeOptionalStringArray(null);
  754. }
  755. out.writeOptionalWriteable(fetchSourceContext);
  756. if (upsertRequest == null) {
  757. out.writeBoolean(false);
  758. } else {
  759. out.writeBoolean(true);
  760. // make sure the basics are set
  761. upsertRequest.index(index);
  762. upsertRequest.type(type);
  763. upsertRequest.id(id);
  764. upsertRequest.writeTo(out);
  765. }
  766. out.writeBoolean(docAsUpsert);
  767. out.writeLong(version);
  768. out.writeByte(versionType.getValue());
  769. out.writeBoolean(detectNoop);
  770. out.writeBoolean(scriptedUpsert);
  771. }
  772. @Override
  773. public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
  774. builder.startObject();
  775. if (docAsUpsert) {
  776. builder.field("doc_as_upsert", docAsUpsert);
  777. }
  778. if (doc != null) {
  779. XContentType xContentType = doc.getContentType();
  780. try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY,
  781. LoggingDeprecationHandler.INSTANCE, doc.source(), xContentType)) {
  782. builder.field("doc");
  783. builder.copyCurrentStructure(parser);
  784. }
  785. }
  786. if (script != null) {
  787. builder.field("script", script);
  788. }
  789. if (upsertRequest != null) {
  790. XContentType xContentType = upsertRequest.getContentType();
  791. try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY,
  792. LoggingDeprecationHandler.INSTANCE, upsertRequest.source(), xContentType)) {
  793. builder.field("upsert");
  794. builder.copyCurrentStructure(parser);
  795. }
  796. }
  797. if (scriptedUpsert) {
  798. builder.field("scripted_upsert", scriptedUpsert);
  799. }
  800. if (detectNoop == false) {
  801. builder.field("detect_noop", detectNoop);
  802. }
  803. if (fetchSourceContext != null) {
  804. builder.field("_source", fetchSourceContext);
  805. }
  806. builder.endObject();
  807. return builder;
  808. }
  809. @Override
  810. public String toString() {
  811. StringBuilder res = new StringBuilder()
  812. .append("update {[").append(index)
  813. .append("][").append(type())
  814. .append("][").append(id).append("]");
  815. res.append(", doc_as_upsert[").append(docAsUpsert).append("]");
  816. if (doc != null) {
  817. res.append(", doc[").append(doc).append("]");
  818. }
  819. if (script != null) {
  820. res.append(", script[").append(script).append("]");
  821. }
  822. if (upsertRequest != null) {
  823. res.append(", upsert[").append(upsertRequest).append("]");
  824. }
  825. res.append(", scripted_upsert[").append(scriptedUpsert).append("]");
  826. res.append(", detect_noop[").append(detectNoop).append("]");
  827. return res.append("}").toString();
  828. }
  829. }