I’ve , but I saw a particular RealmModel written by someone on Stack Overflow, and I felt like I should probably share a few tips on how to a proper Realm schema, or at least simplify things for the . already written a few tips on how to generally use Realm design future It was the following: There’s lots of pain involved with this set of Realm objects. Before we get to that, we should understand a few things: is not relational (it’s NoSQL). As a result of this, there aren’t actual “joins”. Columns aren’t really “columns”, they’re properties of objects. And while there are “ ” as “ ” between objects, it doesn’t work like joins do — it’s essentially a property that points to another object. Realm object links relationships Because is not relational, “normalization” isn’t a requirement. It makes perfect sense to manually create “computed properties”, via overriding the setters for multiple properties, and calculating the value of another property. Realm _RealmObject_s don’t support cascade delete and/or orphan removal, so adding unnecessary objects makes deleting them that much more difficult. models don’t support a whole bunch of things — abstract classes, being abstract themselves, generics, collections that aren’t . They do support interfaces though. Realm RealmList The tips - You should always strive to obtain your list of RealmObjects as the Results returned directly by a query A concrete example. If you have a class, which has a and field, and you want to sort based on ( ), then you obviously can’t express this with a RealmQuery, because custom predicates like that aren’t supported. Product quantity price quantity*price What you CAN however do is defined a THIRD property called “ ”, and update its value in your setters. total Because then you can do And of course, if you use a field in a query, you should definitely put an index on it. - Instead of defining your own “public static final” constants for fields, use the Realm Name Fields Helper There’s which runs an annotation processor and creates these classes for you. this great side thing (unofficially) for Realm by C. Melchior called RealmNamesFieldHelper ___Fields annotationProcessor 'dk.ilios:realmfieldnameshelper:1.1.0' Now you won’t need to make your own constants, and you definitely won’t want to directly write field names by hand. Who does that anyways? - Merge objects into one for uni-directional object links to avoid link queries and manual “cascade deletion” The class I showed at the beginning is a perfect example on how to complicate your life when using Realm. Separating that one class into so many classes makes you need to know their parents (or even parents’ IDs) to query by them efficiently, and this relation would have to be set-up manually because backlinks aren’t yet supported. Email If you query _Email_s by their , you’ll end up using link queries, which are slower and somewhat more complicated to use (and you can’t sort via a link yet). Sender Adding unnecessary object links also make you need to manage their deletion. To delete all objects that belong to a single , you would need to traverse them and call manually on each of them. Email deleteFromRealm() So to refresh our minds, here it is again: And here’s the simplified version: Boom, so much easier to manage! Now you don’t need to tinker with link queries, worry about link sorts, and manage cascade deletes by hand! Having separate objects of unidirectional links gave us no benefit. This of course cannot be done if you have many-relations (RealmList) between the objects. Unfortunately for us, then we’ll still need to separate them. - Handling queries for parent objects without backlinks (pre-3.4.0) This only applies before queries across are introduced. @LinkingObjects If you can’t avoid many relations between your objects, and you can’t use linking objects, then you should still consider being able to create for both sides of the relation. RealmResults For this, you ought to set up the IDs on both sides, kinda like joins (except as you know, there are no joins here). A not-so-concrete example: This way you can query for _Tag_s that belong to a particular post, and you don’t have to manually search through the list in the object. Post - Handling queries for parent objects with backlinks (3.4.0+) Since queries across were introduced, you don’t need to set up bidirectional links. One link to the other will always create an inverse link, which works just like a normal link would. @LinkingObjects Other magical things worth mentioning - I want to store a Map, but Maps are not supported No, but you can store a field that contains the “key” (it could be a String or a primary key of another object). Querying for that “key” field will give you your entry set as a RealmResults for that particular “key”. You can generally avoid maps in your Realm objects, and convert them to queryable fields. - Workaround: if you truly need polymorphism, you can share the fields of the RealmObject via an interface A concrete example. The rank of posts were returned to me by the server, and these ranks were specified by the server. It was paginated too, so you couldn’t just evaluate these ranks by hand on the client. You had to show both the posts on a “normal” feed, and you had to be able to show pretty much the same objects via a “favorited” feed. Needless to say, the primary keys matched. Ranks would have been overwritten. And the way “categories” were managed didn’t make this easier either. I figured I’d just separate my objects into two different “tables”. So there was now a , and a . I also had the feed logic that worked with the properties of a , but I sure wouldn’t want to duplicate it and create a “ ” and “ ”. No way. FeedItem FavoriteFeedItem FeedItem FavoriteFeedView FavoriteFeedAdapter Solution, share the fields via an interface. Creating this interface allowed me to use after some casting magic in my repository. RealmResults<FeedItemInterface> Woo! Now I could use everywhere, with no duplication in actual business logic code! FeedItemInterface - “I don’t really need polymorphism, I just need multiple classes that slightly differ from one another, but share some of the same elements” You can use a String qualifier to determine the type of object your RealmObject is from a set of possible objects, and use the fields that make sense in context of that given subtype. (This technique is also called “ ”). single-table inheritance In my real-life case, this was the selection of its RealmList parameter. I’ll show the whole object just for sake of completeness. had the possible value of , , or . And depending on this value, that particular made sense to use. The others were all empty. But as such, this had mostly unified logic around it. ResultType FIRST SECOND THIRD FOURTH RealmList ResultPost I do admit there was some not very clean magic around it and storing logic in the enum that determined the result type, but it still simplified things for me. But this part is getting very domain-specific, so I’ll leave it at that. Conclusion Hopefully that helped a bit regarding the definition of Realm schema. The greatest take-away is that you should try to minimize your uni-directional object links, unless it’s truly necessary. Uni-directional objects links are common in the typically used workaround for primitive lists, for which you can read **the follow-up article (**about how [R](https://medium.com/@Zhuinden/realmlist-realmstring-is-an-anti-pattern-bfc10efb7ca5)ealmList<RealmString> is bad, and you shouldn’t use it). And as mentioned before, for more Realm-related info, you can always check out my and the articles on the recommended usage of Realm, and the . first second accompanying “tutorial” repository (Reddit discussion thread: ) https://www.reddit.com/r/androiddev/comments/576fl5/designing_the_schema_of_realm_effectively_and/
Share Your Thoughts