Skip to main content

Array

Arrays are an ordered list of values. Arrays can contain all primitive values. You cannot embed other CRDT types inside of an Array. In fact, the Array itself is a register, which makes the behavior different than a typical Array.

warning

Use a Map instead

In Ditto, arrays are treated as atomic, which means that they do not merge when updated. Use an array data type when you want to modify the entire collection of values at the same time.

If you want to modify individual elements independently, use a map data type instead. For more information, see Solution: Use a Map, as follows.

Arrays provide a straightforward way to organize, store, and manipulate data when you want all values within the array to change together, or you need easy access to read-only configuration data. For example:

  • Geographic coordinates — When end users modify their location on a map, both the latitude and longitude values change at the same time. Therefore, using an array [latitude, longitude] is appropriate to store and update the coordinates of a point or a polygon.
  • Configuration data — If you intend for data to be read-only in Ditto, in which data is not modified in Ditto but only referenced in your app, such as legacy data that your app references from an external source like HTTP, using an array to store the configuration values is a good choice.

Problem

If two devices have an instance of an array, and edit those arrays concurrently, their changes may not merge.

For example, assume Device A and B both have the following document at T=1:

{    "_id": "abc123",    "friends": [ "John", "Jacob", "Susan", "Alex" ]}

When Device A and B disconnect from each other, they both update the list of friends:

Device A removes the item at index 1 at T=3:

{    "_id": "abc123",    "friends": [ "John", "Susan", "Alex" ]}

Device B removes the item at index 2 and adds a new item at T=2:

{    "_id": "abc123",    "friends": [ "John", "Jacob", "Alex", "Rebecca" ]}

Because the array is a last-write-wins register, Device A's version of the array will "win." When they synchronize, both Device A and B will see:

{    "_id": "abc123",    "friends": [ "John", "Susan", "Alex" ]}

Device B's changes will be lost.

Solution: Use a Map

You can model a list of strings as a Map with the same behavior as a Set. Ditto doesn't have the Set datatype yet. While we are working on releasing it, you can implement that behavior using a Map.

Given the previous example document:

{    "_id": "abc123",    "friends": [ "John", "Jacob", "Susan", "Alex" ]}

We can convert our existing array to a Map where:

  • the key is a unique string, and
  • the value is an object

Example

Here is sample code that converts an existing Ditto document with an array to a Map.

collection.findByID(docID).update { doc in    guard let doc = doc else {        print("Document with id=\(docID) not found")        return    }
    let names = doc["friends"].arrayValue    var dict = Dictionary<String, Any>()
    _ = names.map { name in        let friend: NSMutableDictionary = [:]        let id = UUID().uuidString        friend["id"] = id        friend["name"] = name        dict.updateValue(friend, forKey: id)    }    doc["friendsMap"].set(dict)}

This code would result in a document that looks like this:

{    "_id": "abc123",    "friends": {        "abc123": { "id": "abc123", "name": "John" },        "def456": { "id": "def456", "name": "Susan" }    }}
New and Improved Docs

Ditto has a new documentation site at https://docs.ditto.live. This legacy site is preserved for historical reference, but its content is not guaranteed to be up to date or accurate.