Upserting and Updating
This article provides an overview of the upsert and update operations:
Following are key distinctions between the update and upsert API methods:
| upsert | update¹ |
Purpose | Does not directly apply changes; you must first retrieve the document. | Directly apply changes to an existing document without needed to first fetch it. |
Document Existence | Does not require the document to exists in Ditto — if the document does not already exists, Ditto automatically creates (inserts) one to store the given fields. | Requires that the document, with the given ID, already exists in Ditto. |
Performance | Less efficient since upserting involves checking whether a document with the given ID already exists and then, as a separate operation, applying the given updates. | More efficient since you do not first fetch a document and then apply updates to it separately. |
Behavior | Optimistic caching: Targets a field locally and, if changed, applies the delta update. | Updates an entire document, even the document fields that remain unchanged. |
¹Not supported in Java
Use the upsert method to achieve any of the following:
- Making changes only to targeted fields
- Creating a new document
- Configuring a custom document ID
For instructions on how to create a new document, see Upserting and Updating.
The following snippet provides the standard upsert syntax, consisting of the document object that you want to upsert and the options you want to set for the upsert:
When writing updates by way of the upsert function:
- If the document already exists, Ditto updates the document with the delta changes.
- If the document does not exist, Ditto automatically creates one.
If not manually supplied, Ditto automatically assigns the new document a unique ID as follows:
Each document must be assigned a unique identifier. When invoking the upsert method to create a new document, unless manually supplied, Ditto automatically generates and assigns the new document a 128‑bit Universally Unique Identifier (UUID).
To configure a custom identifier, when invoking upsert to create a new document, pass the _id parameter in your function.
If supplying your own document ID, you can encode your value in a stringor, if forming a composite key, a JSON blob object made up of two or more values of the string or number type.
You can configure a custom document ID only at the time of document creation.
Once a document is created, to ensure consistency and uniqueness throughout the platform, the unique identifier that either Ditto automatically generated and assigned or you manually assigned becomes permanent and cannot be changed at a later time.
For more information about document IDs, see Platform Manual > Document Model.
For example, the following snippet demonstrates a new document assigned the custom ID abc123.
Following is the new abc123 document that results:
The following snippet demonstrates combining the user_id and work_id fields to form the 456abc789 composite key:
To mitigate the risk of human error when working with composite keys during write operations, it is recommended to use no more than three fields to form your key.
An upsert operation is a combination of the traditional update and insert operations, in which you can insert a new document if it doesn't already exist or update an existing document if it does. This allows you to handle both scenarios within a single operation.
Using the upsert method to update data can cause performance to degrade. To optimize performance and reduce unnecessary overhead, apply most updates in your app through the update method instead. For more information, see Optimizations.
For example, imagine you create the following document in the cars collection:
Once executed, the following document is created as a result:
When you upsert changes, only the fields you supplied will be modified; existing fields remain unchanged. For instance, consider the following upsert in which you change the color "blue" to "red":
As a result, the color changes to "red"; however, make and year remain the same:
Update operations ensure that only the minimum data necessary to enforce all peers converge on one view of the data replicates across the mesh.
Updating an existing document is different depending on the CRDT you're updating:
Operation | Description |
set register | Sets the value for a given field in the document. |
set map | Sets value for a given field in the map. |
remove register | Removes a value for a given field in the document. |
remove map | Removes a value for a given key in the map structure. |
replace with counter | Converts a number value for a given field into a counter. |
increment counter | Unlike a number, increments the counter by the given positive integer value. |
decrement counter | Unlike a number, decrements the counter by the given negative integer value. |