In this tutorial, we focus on updating only specific fields of an existing document in Elasticsearch, rather than replacing the entire document. Although many people casually refer to this as a PATCH-style update, Elasticsearch actually performs this operation using a POST request to a dedicated _update endpoint. Understanding this distinction is important, because the behavior is very different from a full document replacement.
We will explore how partial updates work, how Elasticsearch detects no-op updates, how new fields are added automatically, and how the upsert mechanism helps when a document does not already exist.
Conceptual Overview: How Partial Updates Work
When you want to update only selected fields in a document:
- You do not use the standard index endpoint (
/{index}/_doc/{id}) that replaces the full document. - You use the update endpoint:
/{index}/_update/{id} - You send a POST request, even though the operation behaves like a patch.
- You provide the fields to update inside a
docobject, which tells Elasticsearch to merge these fields into the existing document rather than replacing it entirely.
This approach is safer and more efficient when you only want to modify a few fields.
Step 1: Inspect the Existing Document
Before performing any update, it is always a good practice to first retrieve the document and confirm its current state.
GET books/_doc/3
This request returns the current version of the document with ID 3. For example, suppose the document looks like this:
{
"title": "Some Book",
"author": "Some Author",
"year": 1925
}
Now assume you realize that the year value is incorrect and should be 1926.
Step 2: Update a Single Field Using the _update API
To update only the year field, you send a POST request to the update endpoint and include the updated field inside the doc object.
POST books/_update/3
{
"doc": {
"year": 1926
}
}
What This Does Internally
- Elasticsearch retrieves the existing document.
- It updates only the
yearfield. - All other fields remain unchanged.
- The document is reindexed automatically with the updated content.
If the operation succeeds, the response contains:
{
"result": "updated"
}
Step 3: Verify the Update
Now, fetch the document again:
GET books/_doc/3
You will see that the year field has changed to 1926, while all other fields remain exactly as they were before.
Understanding the noop (No Operation) Result
Now, try sending the same update request again:
POST books/_update/3
{
"doc": {
"year": 1926
}
}
This time, Elasticsearch responds with:
{
"result": "noop"
}
What Does noop Mean?
- Elasticsearch compares the incoming value with the existing value.
- Since
yearis already1926, there is nothing to change. - To avoid unnecessary reindexing, Elasticsearch skips the update.
- This optimization improves performance and reduces disk usage.
Step 4: Adding a New Field That Does Not Exist
Now consider a different scenario. Suppose the document does not have a price field.
Current document:
{
"title": "Some Book",
"author": "Some Author",
"year": 1926
}
If you send the following update request:
POST books/_update/3
{
"doc": {
"price": 499
}
}
What Happens Here?
- Elasticsearch sees that
pricedoes not exist. - Instead of failing, it adds the new field to the document.
- The updated document now includes
pricealong with the existing fields.
Fetching the document again confirms that price has been added successfully.
Step 5: What Happens When the Document ID Does Not Exist?
Now let us try updating a document that does not exist, for example ID 15.
POST books/_update/15
{
"doc": {
"price": 399
}
}
Result
Elasticsearch returns a 404 error:
{
"error": {
"type": "document_missing_exception",
"reason": "[_doc][15]: document missing"
}
}
This happens because, by default, the update API expects the document to exist.
Step 6: Using upsert to Update or Insert
There are many real-world scenarios where you want:
- Update the document if it exists
- Insert the document if it does not exist
This behavior is called upsert (update + insert).
By default, upsert is disabled. To enable it, you must explicitly specify an upsert object.
POST books/_update/15
{
"doc": {
"price": 399
},
"upsert": {
"price": 399
}
}
How This Works
- If document ID
15exists → Elasticsearch updates it. - If document ID
15does not exist → Elasticsearch creates a new document with this ID. - The newly created document will include the fields defined in the
upsertsection.
After sending this request, document ID 15 is created successfully.
Step 7: Verifying the Upserted Document
Now retrieve the document:
GET books/_doc/15
You will see that the document exists and includes the price field as expected.
