Search code examples
realmrealm-mobile-platform

Realm Mobile Platform Architecture - Thousands of realms VS big realm files


I have been trying to find some information about the best ways to architect the data properly using Realm Mobile Platform but I couldn't find relevant architecture documentations.

Let's consider the following scenario:

My database consists of 100,000 movies with data in 50 different languages + for each movies I have the availabilities on 10 VOD platforms in 50 different countries.

One user is interested in a few movies (potentially all of them) ONLY in his language, he may need the availabilities of 3 VOD platforms only in his own country.

It seems absurd to rely on only one realm file as it will be entirely synced on all users devices, so it brings few possibilities:

Solution 1

50 movies realms : 1 for each language containing ALL (100,000) movies

50 availabilities realms : 1 for each country containing ALL (10 VOD providers) availabilities for ALL (100,000) movies

+ No data duplicate, all movies stored locally (local search,...)

- Big realms files to be kept synced

Solution 2

100,000 movies realms : 1 for each movies containing ALL (50) languages and ALL (10 VOD platforms * 50 countries) availabilities

+ Sync only needed movies -> No big initial download

- Need to retrieve (and keep synced?) new realm every time you display a movie in the app, Unneeded data stored on phone (unneeded languages and countries)

Solution 3

1 movie realm per tuple (idMovie, language, country) : 100,000 * 50 * 50 = 250,000,000 realms

+ Sync only what's needed on phone.

- Huge data duplicate (same language different country -> Movie data duplicate + same country different language -> Availability data duplicate), a lot of realms to maintain (how the realm server reacts to that?)

Solution 4

1 movie realm per tuple (language, country) containing the availabilities for each movie : 50 * 50 = 2,500 realms

+ No unneeded data on phone, all movies available locally

- Duplicate availabilities for same country - different languages realms

Solution 5

1 movie realm per tuple (movie,language) : 100,000 * 50 = 5,000,000 realms

1 availability realm per tuple (availability, country) : 100,000 * 50 = 5,000,000 realms

+ No unneeded data on phone, all movies available locally, No duplicate data

- All movies and availabilities should be downloaded at first launch and will be kept synced

PS: Note that in each solution I am storing all VOD providers on the user's device even if he doesn't need it... It's 10 in the example but could be easily 100 in the US.

The Solution 1 seems the most appropriate, but let's say the number of movies (and TV Shows...) grows to 1million or more, the only solution if that's too much to download is to split! The only way would be to use Solution 5, and with 1million movies it would be a total of 100millions realms files to maintain.

How is designed the Realm Mobile Platform and what would be the best solution to avoid unnecessary server overload AND keep the best user experience possible?

Thanks!


Solution

  • Disclaimer: I'm not an official source!

    RMP 1.x required manually managing what you want to sync by building the right sync configuration and storing it in a different Realm, as you had to sync the whole Realm file to query from it. This makes either of the above solutions somewhat tricky.


    With the official release of Realm Mobile Platform 2.0 (2017-10-17), this should actually be quite simple.

    From the docs:

    Part of Realm Platform 2.0, we are launching a preview of partial synchronization. This is a new and exciting capability where client applications can dynamically request data from Realm Object Server by registering queries.

    This is a major change in how application developers can use Realm in their apps. Previously, applications would need to segment their data into multiple Realms to control which data is synced at a given time. Now this can be done entirely in a single Realm!

    The magic is that:

    • SyncConfiguration has a partialRealm() or partial (or similarly named) property

      Realm.open({
          sync: {
              url: `realm://${URL}/tickers`,
              user: user,
              partial: true
          },
          schema: [TickerSchema],
      })
      
    • Realm has a subscribeToObjects() method that can receive a query definition (the Java preview api also uses the Javascript query language at the time of writing in 4.0.0):

      realm.subscribeToObjects('Ticker', 'price > ' + price)
      

    In JS world it returns a promise so you can just do .then((results, error) => {,

    in Obj-C and Java you seem to have to use a callback that will receive the RealmResults that you can subscribe to with a change listener.

    OBJECTIVE-C
    - (void)subscribeToObjects:(nonnull Class)type
                         where:(nonnull NSString *)query
                      callback:(nonnull RLMPartialSyncFetchCallback)callback;
    SWIFT
    func subscribe(toObjects type: AnyClass, where query: String, callback: @escaping RLMPartialSyncFetchCallback)
    
    JAVA
    void subscribeToObjects(Class<E> clazz, String query, Realm.PartialSyncCallback<E> callback)
    

    The callback returns a Results, and you can add the notification block / change listener to that. In Java, you should make sure a reference is stored to the RealmResults.