To-many relationship with foreign keys: best practice

I’m using Sync. I have some data in a collection in a PUBLIC realm, accessible by all users, and a collection of private objects in each user’s personal Realm. I want to setup a many-to-many relationship between these two collections.

Since the collections are not in the same Realm, I have to use foreign keys (strings, the type of my primary keys). I can get back the object by querying the primary keys.

For a list (to-many relationship), here’s what it would look like (example in Swift):

class PublicData: Object {
    @objc dynamic var _id: String = ""
    override class func primaryKey() -> String? { return "_id" }

    // ...
}

class PrivateObject: Object {
    var publicDatas: List<String>

    // ...

    var realData: [PublicData] {
        return Array(publicDatas.map { id in
            publicRealm.object(ofType: PublicData.self, forPrimaryKey: id)!
        })
    }
}

My question: is that efficient, querying primary keys in a loop? Is there a better way to do this, am I missing something?

Hi @Jean-Baptiste_Beau,

Would that make more sense to use the Realm partition key to sync and filter on the MongoDB Rules side the data which is public or specific user id oriented.

Then it feels like you can verify who sees what rather than using relationships which are not so recommended for MongoDB architctures.

Best regards,
Pavel

Hi @Pavel_Duchovny,

Thank you for your reply. However, I’m not sure to understand your point.

The goal of having my static data sitting in a ‘PUBLIC’ Realm is to be able to update it if needed.

Basically, my users will sync to two Realms:

  • the ‘PUBLIC’ realm: read-only for users; the data exists once on the MongoDB database, and all the users sync to it.
  • their personal realm: read and write. There will be one personal Realm for each user.

If I’d want to use only one Realm instead of two, I’d have to copy the static data in every user Realm. The data is not that big, but still this solution feels bad, and I’m not sure maintenance would be easy for this.

Does that address your point or have I misunderstood your answer?
Thanks a lot!

Hi @Jean-Baptiste_Beau,

I think the following section should answer most of your concerns:

https://docs.mongodb.com/realm/sync/partitioning/#example-partitioning-data-across-groups

It feels like some parts of the presented design covers your idea. Let me know if you still have questions.

Best
Pavel

@Pavel_Duchovny in the given example, there are indeed multiple Realms, including one ‘PUBLIC’ and some others, same case as mine. The examples however don’t explain how to structure relationships in this case, since you can’t make relationships between objects in different Realms.

Do you need to store IDs as strings and query the associated objects with a regular query? Or can you somehow structure this in such a way you can have “real” relationships?

Hi @Jean-Baptiste_Beau,

Realm allows you to set relationships in your code:
https://docs.mongodb.com/realm/node/relationships/index.html#key-concepts

As well as on the collection rule side under the relationship tab you can define a list type which is many to many:

Best
Pavel

@Pavel_Duchovny Yes, but these relationships don’t work for objects located in different Realms. How to proceed then?

Hi @Jean-Baptiste_Beau,

What do you mean? What kind of relationship will be there??

@Pavel_Duchovny I recreated a small example similar to my situation:

Say that I have two schemas:

{
  name: "Theme",
  primaryKey: "_id",
  properties: {
    _id: "string",
    _partition: "string",
    name_fr: "string",
    name_eng: "string",
    description_fr: "string",
    description_eng: "string",
  },
}

{
  name: "JournalEntry",
  primaryKey: "_id",
  properties: {
    _id: "string",
    _partition: "string",
    title: "string",
    text: "string",
    theme: Theme,
  },
}

The themes would be public and static. The journal entries would be added by users, and private. This means that I need to use two Realms, one for the partition key PUBLIC, where the themes will be, and one for each user with partition key user_id.

However, I still want a relation between these two objects. In this example, I made the relationship the standard way (theme: Theme), but this won’t work since the objects are in different Realms.

Therefore, from what I understand, I have two solutions:

  1. copy all the themes to each user Realm.
    +: I can use the relationship like above
    —: If I want to update a static data, It’s a nightmare
  2. instead of a theme, store in the journal entries theme_id: string, and query the theme when I need it using the normal realm.object(type, primary_key).
    +: I can update the static data easily
    —: well, that is my question kind of. I find this solution a bit “ugly”, but I’m not really sure what it implies. It needs an additional query, but if the data is synced locally I believe it’s not so much overhead. Is is something that I used by developers in the same situation?

I hope I managed to made myself clearer. This public data / private data combination seems a quite common use case to me, and yet I can’t find any doc that addresses this specifically. What do others do in this case? Did I structure something wrong?

Hey @Jean-Baptiste_Beau,

Shame there isn’t an answer to this, I am about to implement something similar myself. Out of interest did you find a good solution?

Many thanks!

Will

@Jean-Baptiste_Beau Yes - this is exactly what we recommend. You can see a presentation I did that covers this topic - here:

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.