How to Perform an Elasticsearch Update on a Single Field Without Overwriting Other Fields

Use the Update API with a doc payload or Painless script to merge changes into the existing document, leaving unspecified fields untouched.

The Elasticsearch Update API provides a purpose-built mechanism for partial document modifications in the elastic/elasticsearch repository. When you need to modify a single field, this API ensures that only the specified values change while the remaining document structure persists intact.

Understanding the Elasticsearch Update API Architecture

The update workflow centers on the UpdateRequest class located in [server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java). This object encapsulates the target index, document ID, and the partial update definition—either a doc fragment or an inline script.

When the request reaches the cluster, the UpdateAction handler ([UpdateAction.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateAction.java)) orchestrates the execution. The handler retrieves the current _source from the index, applies the supplied changes through the UpdateHelper utility, and reindexes the merged document as a new version. This merge operation guarantees that fields absent from the update request remain unchanged in the stored document.

Methods for Partial Document Updates

Using the Doc Payload for Simple Field Updates

The most efficient approach for a single-field elasticsearch update is passing a partial JSON object via the doc parameter. Elasticsearch performs a fast merge of this fragment against the stored _source, updating only the keys you provide.

REST API Example:

POST /my-index/_update/1
{
  "doc": {
    "status": "closed"
  }
}

Java Client Example:

UpdateRequest request = new UpdateRequest("my-index", "1")
        .doc("status", "closed");

client.update(request, RequestOptions.DEFAULT);

Using Painless Scripts for Computed Updates

When the new value depends on the existing field value—such as incrementing a counter—use a Painless script instead of a static doc. The script executes within the Elasticsearch node, reading the current _source, computing the modification, and writing back only the changed field.

REST API Example:

POST /my-index/_update/1
{
  "script" : {
    "source": "ctx._source.views += params.inc",
    "lang": "painless",
    "params" : {
      "inc" : 1
    }
  }
}

Java Client Example:

UpdateRequest request = new UpdateRequest("my-index", "1")
        .script(new Script(
            ScriptType.INLINE,
            "painless",
            "ctx._source.views += params.increment",
            Collections.singletonMap("increment", 1)));

client.update(request, RequestOptions.DEFAULT);

Optimizing Single-Field Update Performance

To ensure your elasticsearch update operations remain efficient:

  • Avoid sending the full document. Transmitting the entire _source back to Elasticsearch creates unnecessary network overhead and serialization costs. Always use partial doc payloads or targeted scripts.
  • Enable optimistic concurrency control. Include if_seq_no and if_primary_term parameters in your update request to prevent lost updates when multiple clients modify the same document concurrently. The UpdateResponse object ([UpdateResponse.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateResponse.java)) returns the new sequence numbers after each operation.
  • Prefer scripts for atomic operations. When updating counters or arrays, Painless scripts execute atomically on the data node, eliminating race conditions that could occur with read-modify-write cycles in your application code.

Key Source Files in the Elasticsearch Update Workflow

File Role
[UpdateRequest.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java) Represents the client-side request; holds the index, ID, and partial update definition (doc or script).
[UpdateAction.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateAction.java) Server-side transport handler that executes the update, merges the partial source, and reindexes the document.
[UpdateHelper.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateHelper.java) Utility class that reads the existing document, applies the doc or script, and builds the new source for indexing.
[UpdateResponse.java](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateResponse.java) Response object containing versioning information and shard status after the update.

Summary

  • The Update API performs partial document modifications by merging a doc payload or script with the existing _source.
  • Use the doc parameter for simple field updates and Painless scripts for computed values like counters.
  • The Java client constructs an UpdateRequest object, while the server-side UpdateAction handles the merge and reindexing logic.
  • Avoid sending full documents to minimize network overhead, and use if_seq_no/if_primary_term** for optimistic concurrency control.

Frequently Asked Questions

Does the Elasticsearch Update API overwrite the entire document?

No. The Update API is specifically designed to avoid full overwrites. When you provide a doc payload or a script, Elasticsearch retrieves the current _source, applies your changes to merge the new values with the existing fields, and reindexes only the modified document. All unspecified fields remain intact.

What is the difference between using a doc payload and a script for updates?

A doc payload is ideal for setting static values on specific fields, such as changing a status field from "open" to "closed". A script (written in Painless) is required when the new value depends on the current value, such as incrementing a counter or appending to an array. Scripts execute atomically on the data node, eliminating race conditions in read-modify-write scenarios.

How does Elasticsearch handle concurrent updates to the same document?

Elasticsearch uses optimistic concurrency control to manage concurrent modifications. You can include if_seq_no and if_primary_term parameters in your Update request. If the document has been modified since you last read it (meaning the sequence numbers no longer match), Elasticsearch returns a version conflict error (409), allowing your application to retry or resolve the conflict rather than silently losing data.

Can I update a document without retrieving the _source field?

No, the Update API requires access to the _source field to perform the merge operation. When you send a doc or script update, the server must fetch the existing _source, apply your changes, and reindex the result. If you have disabled _source storage for the index, you cannot use the Update API for partial modifications; you must instead use the Index API to replace the entire document.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →