---
title: Upserting and Updating
slug: v4-4/wNiiPaCzTUdAxHZ8OuHhj
docTags: 
createdAt: 2023-07-28T20:02:36.395Z
---

This article provides an overview of the Upsert and Update operations:

- [Key Distinctions](./#key-distinctions)
- [Update](./#update)
- [Upsert](docId\:L2hFjvzUYyNu5ahZXHwAJ)

# Key Distinctions&#x20;

The following table provides an overview of key distinctions between the Update and Upsert methods:

| ****                   | **Upsert Operation**                                                                                                                                                                                                                                                                                                                                                                                                    | **Update Operation¹**                                                                                                                                                                                                                                                                            |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Fetching**           | Unlike Update, does not directly apply changes; you must first retrieve the document.                                                                                                                                                                                                                                                                                                                                   | Directly applies changes to an existing document without needing to fetch it first.                                                                                                                                                                                                              |
| **Document Existence** | Does not require the document to exist in Ditto — if the document does not already exist, Ditto automatically creates (inserts) one to store the given fields.                                                                                                                                                                                                                                                          | Requires that the document, with the given ID, already exists in Ditto.                                                                                                                                                                                                                          |
| **Update Behavior**    | Unlike the update operation, if you perform an upsert with the entire document, rather than with only the specific fields that have changed, the upsert operation modifies all document fields, even if their values remain the same.²<br /><br />To maximize efficiency, when invoking the Upsert method to make changes, instead of upserting the entire document, only upsert the specific fields that have changed. | Maximum efficiency due to optimistic caching: Targets a field locally and, if changed, proceeds to apply the delta update to it.<br />This behavior is the opposite of the upsert operation, which modifies all document fields provided in your upsert, even if their values remain unchanged.³ |
| **Performance**        | Ditto transmits only necessary data changes, the delta, during both upsert and update operations. However, upsert operations may result in network degradation due to their update behavior.³                                                                                                                                                                                                                           | More efficient since you do not first fetch a document and then apply updates to it separately.                                                                                                                                                                                                  |

¹Not supported in Java

²With Ditto’s conflict-free replicated data type (CRDT) technology, a field is not just the value itself but also the time at which the value was sent, known as the *Hybrid Logical Clock&#x20;*(HLC). So although the actual value remains unchanged, at the system level, the field is marked as changed. (See [Sync and Replication Concepts](docId\:Vh2a6OTl4DLnEl0A-mIU8))

³In Ditto, the absence of data does not equate to the removal of data; therefore, when you upsert with only specific fields, Ditto updates only those fields; the data that is absent in your upsert operation is unchanged.

# Upsert

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

:::hint{type="info"}
For instructions on how to create a new document, see [Upserting and Updating](docId\:L2hFjvzUYyNu5ahZXHwAJ).
:::

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:

:::CodeblockTabs
```swift
let documentId = ditto.store
  .collection("your_collection_name")
  .upsert(document, options: options)
```

```kotlin
val documentId = ditto.store
    .collection("your_collection_name")
    .upsert([document], [options])
```

```javascript
const documentId = await ditto.store
  .collection("your_collection_name")
  .upsert([document], [options])
```

```java
DittoDocumentId documentId = ditto.store
  .collection("your_collection_name")
  .upsert([document], [options])
```

```csharp
var documentId = ditto.Store
  .Collection("your_collection_name")
  .Upsert([document], [options]);
```

```cpp
DocumentId documentId = ditto.get_store()
  .collection("your_collection_name")
  .upsert([document], [options])
```

```rust
//basic upsert:

let collection = ditto.store()
  .collection("your_collection_name").unwrap();

let documentId = collection.upsert([document])


//custom upsert based on options:

let documentId = collection.upsert_with_strategy(([document], options)
```
:::

## Creating New Documents

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. &#x20;

:::hint{type="info"}
If not manually supplied, Ditto automatically assigns the new document a unique ID as follows:&#x20;
:::

:::CodeblockTabs
```swift
let docId = ditto.store.collection("your_collection_name").upsert(document)
```

```kotlin
let docId = ditto.store.collection("your_collection_name").upsert(document)

// documentId = "507f191e810c19729de860ea"
```

```javascript
const documentId = await ditto.store
  .collection("cars").upsert({color: "blue"})

console.log(documentId) // "507f191e810c19729de860ea"
```

```java
Map<String, Object> content = new HashMap<>();
content.put("name", "Susan");
content.put("age", 31);
DittoDocumentId docId = ditto.store.collection("people").upsert(content);
// docId => 507f191e810c19729de860ea
```

```csharp
var document = new Dictionary<string, object> {{ "color", "blue" }};
var documentId = ditto.Store.Collection("cars").Upsert(document);

Console.WriteLine(documentId); // "507f191e810c19729de860ea"
```

```cpp
json document = json({{"color", "blue"}});
DocumentId documentId = ditto.get_store()
  .collection("cars")
  .upsert(document)

// documentId = "507f191e810c19729de860ea"
```

```rust
let document = json!({
  "color": "blue".to_string(),
});
let documentId = collection.upsert(document);

// documentId = "507f191e810c19729de860ea"
```
:::

## Supplying a Custom ID

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).&#x20;

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 `string` or, if forming a composite key, a JSON-object.&#x20;

:::hint{type="warning"}
You can configure a custom document ID only at the time of document creation.&#x20;

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&#x20;*> [Document Model](docId\:AmTy0OpHec33HDf-1IOhZ).

### String ID

For example, the following snippet demonstrates a new document assigned the custom ID `abc123`.

:::CodeblockTabs
```swift
do {
    // upsert JSON-compatible data into Ditto
    let docID = try ditto.store["people"].upsert([
        "_id": "abc123",
        "name": "Susan",
        "age": 31
    ])
    print(docID) // "abc123"
} catch {
    //handle error
    print(error)
}
```

```kotlin
val docId = ditto.store["people"].upsert(
    mapOf(
        "_id" to "abc123",
        "name" to "Susan",
        "age" to 31
    )
)
```

```javascript
const document = {
  _id: "abc123",
  name: "Susan",
  age: 31
}
const documentId = await ditto.store.collection("cars").upsert(document)

console.log(documentId) // "abc123"
```

```java
Map<String, Object> content = new HashMap<>();
content.put("_id", "abc123");
content.put("name", "Susan");
content.put("age", 31);

DittoDocumentId docId = ditto.store.collection("people").upsert(content);
// docId => abc123
```

```csharp
var document = new Dictionary<string, object> {
  { "_id", "123456" },
  { "color", "blue" },
};
var documentId = ditto.Store.Collection("cars").Upsert(document);

Console.WriteLine(documentId); // "123456"
```

```cpp
json document = json({{"_id", "123456"}, {"color", "blue"}});
DocumentId documentId = ditto.get_store()
  .collection("cars")
  .upsert(document)

// documentId = "123456"
```

```rust
let doc_id = DocumentId::new(&"123456".to_string()).unwrap();
let document = json!({
  "_id": doc_id,
  "color": "blue".to_string(),
});
let documentId = collection.upsert(document)

// documentId = "123456"
```
:::

Following is the new `abc123` document that results:

```json
{
  "_id": "abc123",
  "name": "Susan",
  "age": 31,
}
```

### Composite ID

The following snippet demonstrates combining the `user_id` and `work_id` fields to form the `456abc789` composite key:

:::hint{type="info"}
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.
:::

:::CodeblockTabs
```swift
do {
    let docID = try ditto.store["people"].upsert([
        "_id": [ "userId": "456abc", "workId": 789 ] as [String : Any],
        "name": "Susan",
        "age": 31
    ])
    print(docID) // "[ "userId": "456abc", "workId": 789 ]"
} catch {
    //handle error
    print(error)
}
```

```kotlin
val docId = ditto.store["people"].upsert(
    mapOf(
        "_id" to mapOf( "userId" to "456abc", "workId" to 789),
        "name" to "Susan",
        "age" to 31
    )
)
```

```javascript
const docID = await ditto.store.collection('cars').upsert({
 _id: {
    user_id: "123abc",
    work_id: 789
  }
})

console.log(docID) // "123abc789"
```

```java
Map<String, Object> _id = new HashMap<>();
_id.put("userId", "456abc");
_id.put("workId", 789);

Map<String, Object> value = new HashMap<>();
value.put("_id", _id);
value.put("name", "Susan");
value.put("age", 31);
DittoDocumentId docID = ditto.store.collection("people").upsert(value);
// docId=> "_id.put("userId", "456abc"); _id.put("workId", 789);"
```

```csharp
var document = new Map<string, object> {
  { 
    { "_id", new Map<string, string> { { "user_id", "123" }, 
    { "work_id", "abc" } } }
};
var documentId = ditto.Store.Collection("cars").Upsert(document);

Console.WriteLine(documentId); // "123abc"
```

```cpp
json content = {
        { "_id", {
            { "userId", "456abc" },
            { "workId", 789 }
        }},
        { "name", "Susan" },
        { "age", 31 }
    };

    DocumentId doc_ID = ditto.get_store().collection("people").upsert(content.dump());
```

```rust
let document_id = ditto.store.collection("cars").upsert(
    maplit::hashmap! {
        "_id" => hashmap! { "userId" => "456abc", "workId" => 789 },
        "name" => "Susan",
        "age" => 31,
    },
);

// document_id = "456abc789"
```
:::

## Upserting Delta Updates

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.

:::hint{type="warning"}
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](docId\:FRdDIGT0LERPqodxLzgYS).&#x20;
:::

For example, imagine you create the following document in the `cars` collection: &#x20;

:::CodeblockTabs
```swift
let docID = try ditto.store["cars"].upsert([
    "_id": "123456",
    "make": "Toyota",
    "color": "blue",
    "year": 2024
])
```

```kotlin
val docID = ditto.store["cars"].upsert(mapOf(
    "_id" to "123456",
    "make" to "Toyota",
    "color" to "blue",
    "year" to 2024
))
```

```javascript
const docID = await ditto.store.collection("cars").upsert({
    _id: "123456",
    make: "Toyota",
    color: "blue",
    year: 2023
})
```

```java
Map<String, Object> content = new HashMap<>();
content.put("_id", "123456");
content.put("make", "Toyota");
content.put("color", "blue");
content.put("year", 2024);
DittoDocumentId docId = ditto.store.collection("cars").upsert(content);
```

```csharp
var docId = ditto.Store.Collection("cars").Upsert(
    new Dictionary<string, object>
    {
        { "_id", "123456" },
        { "model", "Toyota" },
        { "color", "blue" },
        { "year", 2024 }
    }
);  
```

```cpp
json car = {
    {"_id", "123456"},
    {"make", "Toyota"},
    {"_id", "123456"},
    {"_id", "123456"},
};
ditto.get_store().collection("cars").upsert(car);
```

```rust
let doc_id = DocumentId::new(&"123456".to_string()).unwrap();
let car = json!({ // car implements serde::Serialize
    "_id": doc_id,
    "make": "Toyota".to_string(),
    "color": "blue".to_string(),
    "year": 2024,
});
collection.upsert(car).unwrap();
```
:::

Once executed, the following document is created as a result:

```json
{
  "_id": "123456",
  "model": "Toyota",
  "color": "blue",
  "year": 2024
}
```

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"`:

:::CodeblockTabs
```swift
do {
    // find the document by ID
    let document = try ditto.store["cars"].findByID("123456")
    
    // change the color to "red"
    try document?.update({ mutableDoc in
        mutableDoc?["color"] = "red"
    })
} catch {
    // handle error
    print(error)
}
```

```kotlin
try {
    // find the document by ID
    val document = ditto.store["cars"].findByID("123456")
    
    // change the color to "red"
    document?.update { mutableDoc ->
        mutableDoc?.set("color", "red")
    }
} catch (e: Exception) {
    // handle error
    println(e)
}
```

```javascript
try {
    // find the document by ID
    const document = await ditto.store.collection("cars").findByID("123456");
    // change the color to "red"
    await document.update(mutableDoc => {
        mutableDoc.set("color", "red");
    });
} catch (error) {
    // handle error
    console.error(error);
}
```

```java
try {
    // find the document by ID
    DittoDocument document = ditto.store.collection("cars").findByID("123456");

    if (document != null) {
        // change the color to "red"
        document.update(mutableDoc -> {
            mutableDoc.set("color", "red");
        });
    }
} catch (Exception e) {
    // handle error
    e.printStackTrace();
}
```

```csharp
    // find the document by ID
    var document = ditto.Store.Collection("cars").FindByID("123456");

    // change the color to "red"
    document.Update(mutableDoc =>
    {
        mutableDoc.Set("color", "red");
    });
}
// handle error
catch (Exception e)
{
```

```cpp
// find the document by ID and upsert color to "red"
json updatedDocument = {
    {"_id", "123456"},
    {"color", "red"}
};
ditto.get_store().collection("cars").update(car);
```

```rust
// find the document by ID
match ditto.store.collection("cars").find_by_id("123456") {
    Ok(mut document) => {
      // change the color to "red"
        document.update(|mutable_doc| {
            mutable_doc.set("color", "red");
        });
    },
    Err(e) => {
        // Handle error
        println!("{:?}", e);
    }
}
```
:::

As a result, the color changes to `"red"`; however, make and year remain the same:

```json
{
  "_id": "123456",
  "model": "Toyota",
  "color": "red",
  "year": 2024
}
```

# Update

Update operations ensure that only the minimum data necessary to enforce all peers converge on one view of the data replicates across the mesh.

:::CodeblockTabs
```swift
ditto.store["your_collection_name"]
  .findByID("document_ID")
  .update([your update function]) 
```

```kotlin
ditto.store
  .collection("your_collection_name")
  .findByID("document_id")
  .update([your update_function])
```

```javascript
await ditto.store
  .collection("your_collection_name")
  .findByID("document_id")
  .update([update_function])
```

```java
ditto.store.collection("people").findById(docId).update(doc -> {
    try {
        doc.get("age").set(32);
        doc.get("ownedCars").getCounter().increment(1);
    } catch (DittoError err) {
        // Do something with error
    }
});
```

```csharp
ditto.Store
  .Collection("your_collection_name")
  .FindByID("document_id")
  .Update([update_function])
```

```cpp
ditto.get_store()
  .collection("your_collection_name")
  .find_by_id("document_id")
  .update([update_function])
```

```rust
let collection = ditto.store["your_collection_name"];
let document = collection.findByID("document_ID");

if let Some(document) = document {
    let updatedDocument = your_update_function(&document);
    collection.update(updatedDocument);
}
```
:::

## Overview of Behavior by CRDT&#x20;

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. |

