Azure Cosmos DB Documentation

Java SDK

Updating an Item in Azure Cosmos DB with the Java SDK

This document guides you through the process of updating an existing item within an Azure Cosmos DB container using the official Azure Cosmos DB Java SDK.

Note: Updating an item involves replacing the entire item document. For partial updates, you would typically read the item, modify its properties in memory, and then upsert or replace the modified item.

Prerequisites

Key Concepts

The primary method for updating an item is typically by using the upsertItem or replaceItem methods provided by the Cosmos DB client.

Both methods require the item's ID and the item object itself (which should contain the updated data). It's crucial to include the _etag property if you are using optimistic concurrency control (which is highly recommended for concurrent updates).

Example: Using upsertItem to Update an Item

This example demonstrates how to update a Product item. We'll assume you have a POJO class named Product.

First, ensure you have your Product class defined:


public class Product {
    private String id;
    private String name;
    private String category;
    private double price;
    private String _etag; // For optimistic concurrency control

    // Getters and Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getCategory() { return category; }
    public void setCategory(String category) { this.category = category; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
    public String get_etag() { return _etag; }
    public void set_etag(String _etag) { this._etag = _etag; }

    // Optional: Constructor
    public Product() {}

    public Product(String id, String name, String category, double price) {
        this.id = id;
        this.name = name;
        this.category = category;
        this.price = price;
    }
}
        

Now, here's the code to update an item:


import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.CosmosResponse;
import com.azure.cosmos.models.CosmosItemResponse;
import com.azure.cosmos.models.PartitionKey;
import com.azure.cosmos.models.CosmosItemRequestOptions;

import java.time.Duration;

public class UpdateCosmosItem {

    private static final String ENDPOINT = "";
    private static final String KEY = "";
    private static final String DATABASE_ID = "YourDatabaseId";
    private static final String CONTAINER_ID = "YourContainerId";

    public static void main(String[] args) {

        // Initialize Cosmos Client
        try (CosmosClient client = new CosmosClientBuilder()
                .endpoint(ENDPOINT)
                .key(KEY)
                .consistencyLevel("SESSION") // Or your preferred consistency level
                .buildClient()) {

            // Get database and container
            CosmosDatabase database = client.getDatabase(DATABASE_ID);
            CosmosContainer container = database.getContainer(CONTAINER_ID);

            // ID of the item to update
            String itemId = "existing-item-id-123";
            String partitionKeyPath = "your-partition-key-value"; // e.g., "Electronics"

            // 1. Read the existing item to get its _etag and current data
            System.out.println("Reading item to prepare for update...");
            CosmosItemResponse readResponse = container.readItem(
                itemId,
                new PartitionKey(partitionKeyPath),
                Product.class
            );

            Product existingProduct = readResponse.getItem();
            String currentEtag = existingProduct.get_etag();
            System.out.println("Read item with ID: " + itemId + ", ETag: " + currentEtag);

            // 2. Modify the item in memory
            existingProduct.setPrice(existingProduct.getPrice() * 1.10); // Increase price by 10%
            existingProduct.setCategory("Updated Category"); // Update category

            // IMPORTANT: Ensure the _etag is set for optimistic concurrency
            // The SDK usually handles this if you retrieve the item first.
            // If you manually construct the item to update, ensure you copy the _etag.
            // In this case, `existingProduct` already has the _etag from the read operation.

            // 3. Prepare request options for optimistic concurrency
            CosmosItemRequestOptions requestOptions = new CosmosItemRequestOptions();
            // If etag is null, it means the item wasn't found or _etag wasn't retrieved correctly.
            // Handle this scenario as per your application logic.
            if (currentEtag != null) {
                requestOptions.setIfMatchETag(currentEtag);
                System.out.println("Setting If-Match ETag for update: " + currentEtag);
            } else {
                System.err.println("Warning: ETag not retrieved. Update might fail or create a new item if upserting.");
                // Depending on your strictness, you might want to throw an exception here
                // or let upsertItem handle it (which might create a new item if none exists).
            }

            // 4. Update (upsert) the item
            System.out.println("Upserting item with updated data...");
            CosmosItemResponse upsertResponse = container.upsertItem(
                existingProduct, // The modified item object
                new PartitionKey(partitionKeyPath),
                requestOptions // Include options for concurrency
            );

            System.out.println("Item updated successfully!");
            System.out.println("New ETag: " + upsertResponse.getItem().get_etag());
            System.out.println("Request charge: " + upsertResponse.getRequestCharge());
            System.out.println("Status code: " + upsertResponse.getStatusCode());

        } catch (Exception e) {
            System.err.println("Error updating item: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
        

Explanation

  1. Initialize Cosmos Client: Establish a connection to your Azure Cosmos DB account using your endpoint and key.
  2. Get Database and Container: Obtain references to your target database and container.
  3. Read Existing Item: It's best practice to first read the item you intend to update. This retrieves the current state of the item, including its unique _etag. The _etag is crucial for optimistic concurrency control.
  4. Modify Item: Update the properties of the Product object in memory.
  5. Set Optimistic Concurrency: Create a CosmosItemRequestOptions object and set the ifMatchETag property to the _etag obtained from the read operation. This ensures that the update will only succeed if the item hasn't been modified by another client since it was read. If the _etag does not match, Cosmos DB will return a 412 Precondition Failed error.
  6. Upsert Item: Call the upsertItem method on the container, passing the modified item object, its partition key, and the request options.
  7. Handle Response: The CosmosItemResponse contains details about the operation, including the status code and request charge.

Using replaceItem

If you want to strictly enforce that the item must exist (and fail if it doesn't), you can use replaceItem instead of upsertItem. The process is nearly identical, with the only change being the method call:


// ... (previous setup code) ...

            // 4. Replace the item
            System.out.println("Replacing item with updated data...");
            CosmosItemResponse replaceResponse = container.replaceItem(
                existingProduct, // The modified item object
                new PartitionKey(partitionKeyPath),
                requestOptions // Include options for concurrency
            );

            System.out.println("Item replaced successfully!");
            System.out.println("New ETag: " + replaceResponse.getItem().get_etag());
            System.out.println("Request charge: " + replaceResponse.getRequestCharge());
            System.out.println("Status code: " + replaceResponse.getStatusCode());

// ... (rest of the code) ...
        

Important Considerations

Related API References