The MAP type uses the add-wins approach to resolving concurrency conflicts.

So instead of choosing a single definitive value to merge and distribute across peers like the last-write-wins strategy utilized by the REGISTER and ATTACHMENT data types, choose them all — even if the data is already contained within the MAP object.

Comparing a JSON Object

The MAP data type in DQL forms a tree-like, parent-child relationship within a document’s dataset. This is similar to a JSON object, which functions as a single unit. However, a MAP allows:

  • Nesting of various DQL data types:REGISTER, MAP, and ATTACHMENT as values for its keys.

  • Each key-value pair within a MAP can be modified independently without affecting other pairs.

  • Utilization of an add-wins merge strategy for conflict resolution. When conflicting changes occur during sync, all conflicting changes are retained rather than converging on only one. This ensures that no data is lost.

MAP Data Structure

The response structure of a MAP is a JSON-like object; however, each field in a MAP has a corresponding data type. This means that each field within a MAP has an independent merge definition the same as fields on the top-level document.

The MAP type is useful when creating a list of non-conflicting items and updating items over time within a document.

The following snippet demonstrates a Ditto document with an embedded MAP my_map:

Ditto Document
{
  "_id": "123"
  "my_map": {
    "sub_field": "value",
  }
}

Declaring a MAP

The REGISTER is the default data type in Ditto; therefore, there is no need for explicit declaration — it’s implicitly assumed.

However, to use a MAP (and ATTACHMENT) data type, you must explicitly declare it within your DQL statement using t*ype definition *syntax.

A type definition is a description informing Ditto that the given set of key-value pairs embedded in the document as a nested structure is distinct from the default REGISTER type. This definition specifies how Ditto should handle the dataset within that nested structure.

To declare a data type a MAP, you use the COLLECTION identifier prefix, followed by the collection name enclosed in parentheses alongside a type definition. All done inline as follows:

DQL
... COLLECTION your_collection_name (my_map_1 MAP, my_map_2 MAP, ...) ...

For more information and how-to instructions, see *Ditto Query Language *> Types and Definitions

Merge Strategy with MAP

The MAP type has an add-wins merge behavior. This means that the adding or updating of a field always wins over the removal (tombstone) of the same field when performing a merge across two peers.

Conflicts with Multiple Field Entries

If multiple fields are added across Small Peer devices, the result will be a MAP with all added fields. This is because each field within a MAP is associated with a distinct data type; that is, each can be represented as a REGISTER, MAP, or an ATTACHMENT.

That means, unlike a JSON blob object, which acts as a REGISTER functioning as a single unit, the merge strategy for each field within a MAP object depends on each of their data type representation.

In the following example, USER 1 inserts item1 and USER 2 inserts item2 to an items MAP:

DQL
# USER 1 adds item1
UPDATE COLLECTION my_collection (items MAP)
SET
  items -> (item1 = 'red')
WHERE
  _id = '123'
DQL
# USER 2 adds item2
UPDATE COLLECTION my_collection (items MAP)
SET
  items -> (item2 = 'blue')
WHERE
  _id = '123'

The resulting document contains an items MAP with both item1 and item2:

Ditto Document
{
  "_id": "123"
  "items": {
    "item1": "red",
    "item2": "blue",
  }
}

Comparing MAP With REGISTER Types

The nested JSON object functions as a REGISTER and closely resembles a nested MAP structure within a document. However, their merge strategies and supported types for nested values are significantly different.

Understanding these distinctions is crucial when selecting the appropriate data type for expressing your data structure.

Example Scenario

For example, consider a document with a properties field of the REGISTER data type storing information about a car in an embedded JSON object.

You want to change only the color field for a car identified by document ID 123 to blue.

Since a REGISTER acts as a single object, to update just the color, you’d need to update the entire object by providing the entire set of nested key-value pairs, including the modified color , as follows:

let newProperties = [
  "color": "blue",
  "sunroof": true,
  "door_count": 4
]

await ditto.store.execute(
  "UPDATE cars SET properties = :newProperties WHERE _id = '123'",
  ["newProperties": newProperties]);

However, if the properties field is of the `

Was this page helpful?