Learnitweb

Updating Specific Fields in an Elasticsearch Document

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 doc object, 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 year field.
  • 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 year is already 1926, 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 price does not exist.
  • Instead of failing, it adds the new field to the document.
  • The updated document now includes price along 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 15 exists → Elasticsearch updates it.
  • If document ID 15 does not exist → Elasticsearch creates a new document with this ID.
  • The newly created document will include the fields defined in the upsert section.

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.