Use device sync with schema-less document parts

I’m trying to implement Realm flexible sync, which works great when having a fixed schema. However, in my case, a part of the document is schema-less, and the exact structure is unpredictable and can differ per document instance.

I tried to include an object property with “additionalProperties: true” to allow varying content (free structure), but this only works when putting primitive properties inside the object. When adding complex property types, like nested objects, the documents are being ignored (not read/synced) when using device sync.

The schema looks like this:

{
    "title": "AgendaItem",
    "bsonType": "object",
    "required": ["_id", "tenant", "date"],
    "properties": {
        "_id": { "bsonType": "objectId" },
        "tenant": { "bsonType": "objectId" },
        "date": { "bsonType": "string" },
        "attributes": {
            "bsonType": "object",
            "additionalProperties": true
        }
    }
}

This document works (at least it is being read by the client):

{
  "_id": "xyz",
  "tenant": "t1",
  "date": "2020-01-01",
  "attributes": {
    "foo": "bar"
  }
}

But this does not work (the document is not being read when starting sync):

{
  "_id": "xyz",
  "tenant": "t1",
  "date": "2020-01-01",
  "attributes": {
    "foo": {
      "bar": "baz"
    }
  }
}

Is it expected behaviour that complex structures are not supported? Is there any other way to accomplish a flexible (partial) document structure? Thanks!

1 Like

Sync uses the schema to translate the MongoDB data to Realm objects, and vice versa. There’s not currently a way for it to have a “partial schema.”

I’m not sure what SDK you’re using - have you considered making your attributes property use the Realm mixed data type? In the Swift SDK, this is AnyRealmValue, and it supports both primitives and objects. There are some limits - it doesn’t currently support EmbeddedObject or collection types, for example. But it offers some flexibility where the data may vary.

Thanks for the quick answer!

According to the docs, the “mixed” type indeed would support both primitives and objects (but not dictionaries). However, when setting the type for “attributes” to mixed, the following object is still not being synced:

{
  "_id": "xyz",
  "tenant": "t1",
  "date": "2020-01-01",
  "attributes": {
    "foo": "bar"
  }
}

It is completely left out of the synced collection (received by the client). I am managing the schema server-side. This the schema being used for this example:

{
    "title": "AgendaItem",
    "bsonType": "object",
    "required": ["_id", "tenant", "date"],
    "properties": {
        "_id": { "bsonType": "objectId" },
        "tenant": { "bsonType": "objectId" },
        "date": { "bsonType": "string" },
        "attributes": { "bsonType": "mixed" }
    }
}

What would be the right way to get this working? I am using the Node.js SDK.