This documentation is provided as a resource for participants in the private preview of Azure Cosmos DB partial document update.
Note: the partial document update preview is applicable to Core (SQL) API only. Users looking for partial updates in MongoDB API are advised to use the partial update operators (e.g. $set
, $inc
, etc) in db.collection.update()
and db.collection.findAndModify()
.
Please do provide us your feedback, questions or comments via the "issues" section on this repo (second tab on the top left)
Azure Cosmos DB partial document update is a top-level REST API to modify an item efficiently by sending only the modified properties/fields in a document from the client side as opposed to requiring the client to perform a full document replace.
- Reduced network call payload, avoiding whole document to be sent on the wire
- Avoiding extra “READ “operation for OCC check by the client and hence saving on the extra read RU charges
- Significant savings on end-to-end latency for a modifying the document
- Avoid extra CPU cycles on client side to read doc, perform occ checks, locally patch document & then send it over the wire as replace API call
- Multi-region write (formerly "multi-master") conflict resolution to be transparent and automatic with path updates on discrete paths with the same document
- Add
- Remove
- Replace
- Set
- Increment as plus or minus “x”, i.e +/- X
- Conditional patch based on a SQL-like filter predicate
- Single item patch operation command
- Multiple items patch operation in using bulk APIs
- Transactional batch patch operation
- .NET
- Java
- NodeJS
Step 1: Whitelist your account by completing the nomination form : https://aka.ms/cosmos-partial-doc-update or emailing us cosmosdbpatchpreview@microsoft.com for specific clarifications.
Step2: Download the Nuget Package / Maven package
- .NET Nuget Package : NuGet Gallery | Microsoft.Azure.Cosmos 3.18.0-preview or attached nuget file in this repo
- Java Maven Package: Maven Repository: com.azure » azure-cosmos » 4.15.0-beta.1(https://mvnrepository.com/artifact/com.azure/azure-cosmos/4.15.0-beta.1)
Step3: Send us your feedback, comments, questions using the Issues tab on this repo.
During preview the JSON Patch feature can take 5-8 minutes to be enabled after Collection is created. This will not happen after GA as it would be enabled by default. So, for preview, ensure that you are not using newly created Collections. If you do, you may experience error 500 "An unknown error occurred while processing this request.
The full sample is found at .NET v3 samples
//using PatchOperation command to Replace a property. The Patch is issued based on ID lookup for an id = 5, partition key value of pkey and setting TotalDues value to 0
Console.WriteLine("\n1.6 - Patching a item using its Id");
ItemResponse<item> response = await container.PatchItemAsync<item>(
id: 5,
partitionKey: new PartitionKey(“pkey”),
patchOperations: new[] { PatchOperation.Replace("/TotalDue", 0) });
//using PatchOperation command to do multiple patches on a document. The Patch is issued based on ID lookup for an id = 5, partition key value of pkey.
Console.WriteLine("\n1.6 - Patching a item using its Id");
List<PatchOperation> patchOperations = new List<PatchOperation>();
patchOperations.Add(PatchOperation.Add("/nonExistentParent/Child", "bar"));
patchOperations.Add(PatchOperation.Remove("/cost"));
patchOperations.Add(PatchOperation.Increment("/taskNum", 6));
patchOperations.Add(patchOperation.Set("/existingPath/newproperty",value));
container.PatchItemAsync<item>(
id: 5,
partitionKey: new PartitionKey(“pkey”),
patchOperations: patchOperations );
//using Conditional Patch Operation command to replace a property. The patch is issued based on a filter predicate condition; issued to id =5, partition key “pkey” and replaing the Shipped Date to current Datetime
PatchItemRequestOptions patchItemRequestOptions = new PatchItemRequestOptions
{
FilterPredicate = "from c where (c.TotalDue = 0 OR NOT IS_DEFINED(c.TotalDue))"
};
response = await container.PatchItemAsync<SalesOrder>(
id: 5,
partitionKey: new PartitionKey(“pkey”),
patchOperations: new[] { PatchOperation.Replace("/ShippedDate", DateTime.UtcNow) },
patchItemRequestOptions);
List<PatchOperation> patchOperationsUpdateTaskNum12 = new List<PatchOperation>()
{
PatchOperation.Add("/children/1/pk", "patched"),
PatchOperation.Remove("/description"),
PatchOperation.Add("/taskNum", 8)
PatchOperation.Replace("/taskNum", 12)
};
TransactionalBatchPatchItemRequestOptions requestOptionsFalse = new TransactionalBatchPatchItemRequestOptions()
{
FilterPredicate = "from c where c.taskNum = 3"
};
TransactionalBatchInternal transactionalBatchInternalFalse = (TransactionalBatchInternal)containerInternal.CreateTransactionalBatch(new Cosmos.PartitionKey(testItem.pk));
transactionalBatchInternalFalse.PatchItem(id: testItem1.id, patchOperationsUpdateTaskNum12, requestOptionsFalse);
transactionalBatchInternalFalse.PatchItem(id: testItem2.id, patchOperationsUpdateTaskNum12, requestOptionsFalse);
transactionalBatchInternalFalse.ExecuteAsync());
The Maven package is found at Maven Repository: com.azure » azure-cosmos » 4.15.0-beta.1 (mvnrepository.com)
//using PatchOperation command to do multiple patches on a document. The Patch is issued based on ID lookup for an testitem.id, partition key value of testitem.status.
CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create();
cosmosPatchOperations.add("/children/1/CamelCase", "patched");
cosmosPatchOperations.remove("/description");
cosmosPatchOperations.replace("/taskNum", newTaskNum);
cosmosPatchOperations.set("/valid", false);
CosmosPatchItemRequestOptions options = new CosmosPatchItemRequestOptions();
CosmosItemResponse<ToDoActivity> response = this.container.patchItem(
testItem.id,
new PartitionKey(testItem.status),
cosmosPatchOperations,
options,
ToDoActivity.class);
//using Conditional Patch options. The patch is issued based on a filter predicate condition; issued to id = testitem.id, partition key “testitem.status”
CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create();
cosmosPatchOperations.add("/children/1/CamelCase", "patched");
cosmosPatchOperations.remove("/description");
cosmosPatchOperations.replace("/taskNum", newTaskNum);
cosmosPatchOperations.set("/valid", false);
CosmosPatchItemRequestOptions options = new CosmosPatchItemRequestOptions();
options.setFilterPredicate("from root where root.taskNum = " + conditionvalue);
CosmosItemResponse<ToDoActivity> responseFail = this.container.patchItem(
testItem.id,
new PartitionKey(testItem.status),
cosmosPatchOperations,
options,
ToDoActivity.class);
CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create();
cosmosPatchOperations.set("/cost", testDoc.getCost() + 12);
//for conditional filter predicate - optional
TransactionalBatchPatchItemRequestOptions transactionalBatchPatchItemRequestOptionsTrue = new TransactionalBatchPatchItemRequestOptions();
transactionalBatchPatchItemRequestOptionsTrue.setFilterPredicate("from root where root.cost = " + costValue);
TransactionalBatch batch = TransactionalBatch.createTransactionalBatch(this.getPartitionKey(this.partitionKey1));
batch.createItemOperation(testDoc);
batch.patchItemOperation(testDoc.getId(), cosmosPatchOperations);
TransactionalBatchResponse batchResponse = container.executeTransactionalBatch(batch).block();
The npm package can be found at NPM package: com.azure » @azure/cosmos » 3.14.1 (npmjs.com)
const replaceOperation: PatchOperation[] =
[{
op: "replace",
path: "/lastName",
value: "Martin"
}];
const { resource: testItem1 } = await container.item(testItem.lastName).patch(replaceOperation);
const multipleOperations: PatchOperation[] = [
{
op: "add",
path: "/aka",
value: "MeFamily"
},
{
op: "replace",
path: "/lastName",
value: "Jose"
},
{
op: "remove",
path: "/parents"
},
{
op: "set",
path: "/address/zip",
value: 90211
},
{
op: "incr",
path: "/address/zip",
value: 5
}
];
const { resource: testItem2 } = await container.item(testItem.id).patch(multipleOperations);
const operations : PatchOperation[] = [
{
op: "add",
path: "/newImproved",
value: "it works"
}
];
const condition = "from c where NOT IS_DEFINED(c.newImproved)";
const { resource: testItem3 } = await container.item(testItem.id).patch({ condition, operations });
const operations = [
{
operationType: BulkOperationType.Patch,
partitionKey: {},
id: patchItemId,
resourceBody: {
operations: [{ op: PatchOperationType.set, path: "/class", value: "2021" }]
}
}
];
const response = await container.items.bulk(operations);
Azure Cosmos DB partial document update is inspired by JSON patch and follows it closely. Currently we do not implement all features of JSON patch such as (Copy, Move) and we do implement few other features (Conditional Patch) which is not in the specification
Is partial document update compatible with serverless , provisioned throughput and autoscale modes of billing?
Partial document update will be available across serverless and provisioned billing models.
Partial document update is normalized into request unit billing in the same style as other database operations. Users should not expect a significant reduction in RU.
For a detailed answer, refer to this issue
Is there a limit to the number of partial document updates operations that can be done within a single patch specification?
There is a limit of 10 patch operations that can be added in a single patch specification. If we need this number to be increased, please send us an email
We do not support Patch API on system properties. However, if you want it for some usecase, you can send an email and we can enable this for your account.
Yes, please follow the below steps to enable it.
- Download the latest Azure CosmosDB emulator from https://aka.ms/cosmosdb-emulator
- Open PowerShell in admin mode
- cd 'C:\Program Files\Azure Cosmos DB Emulator'
- C:\Program Files\Azure Cosmos DB Emulator> .\CosmosDB.Emulator.exe /EnablePreview