Search code examples
databasemongodbsynchronizationrealmrealm-mobile-platform

Allow users to read multiple partitions in Realm Sync


I am trying to learn and setup Realm Sync. I have setup a database and a react native project to connect to it. My database should have public data, which everyone should be able to read, and user specific data. As far as I know you can manage the access with the sync rules. My current rules are:

READ:

{
  "$or": [
    {
      "%%user.id": "%%partition"
    },
    {
      "%%partition": "PUBLIC"
    }
  ]
}

WRITE:

{
  "%%user.id": "%%partition"
}

Somehow these rules, don't work like desired. When using the users id as a partition value, I receive the data from the user, but not the public one. Other way around, when using PUBLIC as the partition value, I just receive the public data, but not the user data. This part makes sense to, which leads me to believe the sync rules for the read permissions don't work correctly. Checking the docs it should work with my current rules. Is there something I am missing?


Solution

  • I had the same requirements for my React Native app. It also need to have public data and private data (for the current signed in user) synced.

    Strangely enough, the documentation is not very helpful on this matter.

    According to this post from Ian_Ward, a MongoDB employee on the official forum, it's not possible to have more than one partition key when opening a Realm database. Therefore, the solution is to open multiple Realm database (one per partition key).

    Ian_Ward: "You would need to open two separate realms by supplying each with a separate partitionKey value. You should be able to open them both at the same time."

    In our case for example, it means:

    • opening a 1st database to get the public available data
    • opening a 2nd database for the user-specific data
    const realmPublic = await Realm.open({
        schema: [ContactRealm.schema],
        sync: {
            user, // It can be the instance of the signed in user, or even Realm.Credentials.anonymous()
            partitionValue: 'public',
        },
    });
    
    const realmUser = await Realm.open({
        schema: [ContactRealm.schema],
        sync: {
            user, // MUST be the instance of the signed in user 
            partitionValue: `user=${user.id}`,
        },
    });