realmrealm-cocoa

Proper way to implement one-to-many relationship in Realm


I've studied the documentation for Realm and understand the various classes that can be used to manage groups of objects. From what I understand, there are RLMArrays, RLMLinkingObjects, and RLMResults. I will use an example of a Blog class with many objects of class Comments to setup my question. Assuming the Blog class can have 10000s of objects, and each Blog object can have 1000s of Comments, it's not clear to me how best to express the relations in Realm. I could use an RLMArray of comments as a property for the Blog. Then I will have to manage the reverse linkage of Blogs and Comments. That leads me to the RLMLinkingObjects since I can express the comments property on the blog as any comments that link back to the blog. Then there is the complication that there are many more blogs and comments than I would want to instantiate at once. This is where the RLMResults option is attractive since it allows objects to be instantiated lazily. However, this changes the nature of how I interface with the objects since I'll now be querying for comments associated with a blog rather than simply accessing the property (e.g. blog.comments).

I've left out a big consideration here which is that this data all resides on a server, but I'm hoping to define the object model locally (with persistence) first, then figure out how to map the model over REST to a server.

I'd love any input, thoughts, or suggestions from Realm users out there.

Thanks!


Solution

  • Yep! You're on the right track. A Blog object could have multiple Comment objects assigned to it, so it's appropriate to use an RLMArray property in Blog to manage all of its comments. You can then use RLMLinkingObjects to check which Blog object a particular Comment belongs to.

    @interface Comment : RLMObject
    @property (readonly) RLMLinkingObjects *blog;
    @property NSString *message;
    @end
    
    @implementation Comment
    + (NSDictionary *)linkingObjectsProperties {
        return @{
            @"blog": [RLMPropertyDescriptor descriptorWithClass:Blog.class propertyName:@"comments"],
        };
    }
    @end
    RLM_ARRAY_TYPE(Comment)
    
    @interface Blog : RLMObject
    @property RLMArray<Comment *><Comment> *comments;
    @end
    
    @implementation Blog
    @end
    

    RLMArray behaves just like RLMResults; it's lazily-loads data and is a live reference to the underlying content. So you could easily rely on RLMArray in this case without any worries. :)

    While there aren't any official solutions, there are a lot of third party libraries that help map JSON data from REST APIs to Realm (For example https://github.com/matthewcheok/Realm-JSON) so its might be worth checking them out. Either way, as long as the schema locally and remotely is relatively similar, you should be able to map it without too much trouble.

    I hope that helped!