Platform Manual
CRUD Operations
Upserting and Updating
this article provides an overview of the upsert and update operations /#key distinctions /#update docid\ l2hfjvzuyynu5ahzxhwaj key distinctions 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 ² 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 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 (hlc) so although the actual value remains unchanged, at the system level, the field is marked as changed (see 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 for instructions on how to create a new document, see 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 let documentid = ditto store collection("your collection name") upsert(document, options options)val documentid = ditto store collection("your collection name") upsert(\[document], \[options])const documentid = await ditto store collection("your collection name") upsert(\[document], \[options])dittodocumentid documentid = ditto store collection("your collection name") upsert(\[document], \[options])var documentid = ditto store collection("your collection name") upsert(\[document], \[options]);documentid documentid = ditto get store() collection("your collection name") upsert(\[document], \[options])//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 if not manually supplied, ditto automatically assigns the new document a unique id as follows let docid = ditto store collection("your collection name") upsert(document)let docid = ditto store collection("your collection name") upsert(document) // documentid = "507f191e810c19729de860ea"const documentid = await ditto store collection("cars") upsert({color "blue"}) console log(documentid) // "507f191e810c19729de860ea"map\<string, object> content = new hashmap<>(); content put("name", "susan"); content put("age", 31); dittodocumentid docid = ditto store collection("people") upsert(content); // docid => 507f191e810c19729de860eavar document = new dictionary\<string, object> {{ "color", "blue" }}; var documentid = ditto store collection("cars") upsert(document); console writeline(documentid); // "507f191e810c19729de860ea"json document = json({{"color", "blue"}}); documentid documentid = ditto get store() collection("cars") upsert(document) // documentid = "507f191e810c19729de860ea"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) 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 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 > docid\ amty0ophec33hdf 1iohz string id for example, the following snippet demonstrates a new document assigned the custom id abc123 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) }val docid = ditto store\["people"] upsert( mapof( " id" to "abc123", "name" to "susan", "age" to 31 ) )const document = { id "abc123", name "susan", age 31 } const documentid = await ditto store collection("cars") upsert(document) console log(documentid) // "abc123"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 => abc123var document = new dictionary\<string, object> { { " id", "123456" }, { "color", "blue" }, }; var documentid = ditto store collection("cars") upsert(document); console writeline(documentid); // "123456"json document = json({{" id", "123456"}, {"color", "blue"}}); documentid documentid = ditto get store() collection("cars") upsert(document) // documentid = "123456"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 { " 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 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 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) }val docid = ditto store\["people"] upsert( mapof( " id" to mapof( "userid" to "456abc", "workid" to 789), "name" to "susan", "age" to 31 ) )const docid = await ditto store collection('cars') upsert({ id { user id "123abc", work id 789 } }) console log(docid) // "123abc789"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);"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"json content = { { " id", { { "userid", "456abc" }, { "workid", 789 } }}, { "name", "susan" }, { "age", 31 } }; documentid doc id = ditto get store() collection("people") upsert(content dump());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 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 docid\ frddigt0lerpqodxlzgys for example, imagine you create the following document in the cars collection let docid = try ditto store\["cars"] upsert(\[ " id" "123456", "make" "toyota", "color" "blue", "year" 2024 ])val docid = ditto store\["cars"] upsert(mapof( " id" to "123456", "make" to "toyota", "color" to "blue", "year" to 2024 ))const docid = await ditto store collection("cars") upsert({ id "123456", make "toyota", color "blue", year 2023 })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);var docid = ditto store collection("cars") upsert( new dictionary\<string, object> { { " id", "123456" }, { "model", "toyota" }, { "color", "blue" }, { "year", 2024 } } ); json car = { {" id", "123456"}, {"make", "toyota"}, {" id", "123456"}, {" id", "123456"}, }; ditto get store() collection("cars") upsert(car);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 { " 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" 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) }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) }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); }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(); } // 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) {// find the document by id and upsert color to "red" json updateddocument = { {" id", "123456"}, {"color", "red"} }; ditto get store() collection("cars") update(car);// 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 { " 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 ditto store\["your collection name"] findbyid("document id") update(\[your update function]) ditto store collection("your collection name") findbyid("document id") update(\[your update function])await ditto store collection("your collection name") findbyid("document id") update(\[update function])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 } });ditto store collection("your collection name") findbyid("document id") update(\[update function])ditto get store() collection("your collection name") find by id("document id") update(\[update function])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 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