Trying to migrate from Local Realm to MongoDB Realm Sync

I have been using Realm for many years in an app. I just upgraded to the latest version of Realm (10.8.1) and am struggling to convert my local realm to a synced realm.

I use/create realms throughout the app using let realm = try! Realm() after setting Realm.Configuration.defaultConfiguration = config in App Delegate. The config object contains migration blocks that I have added.

From what I understand my objects now need a _id field, but I also need to create an App object, log in and then use the app users configuration to create a new realm. If I do that, I lose all the old data. First, how can I copy the old local realm data to the new synced realm? Second, can I set the defaultConfiguration to the new synced realm configuration, so I can continue using the same old try! Realm() everywhere, or is there a better practice?

Hi, @realm_guy – welcome to the community forum!

From your description, I’m assuming that you’re not using the legacy Realm sync solution (if you are, then this guide can help Realm Legacy Migration Guide - Realm Legacy Migration Guide).

You are correct that to use MongoDB Realm Sync, you need to include an _id attribute in your Objects.

I’m not aware of an automated way of moving Objects from one realm to another and so I think you’ll have to write your own deep copy/transform function in your app.

You should be able to set your default realm to your synced realm.

Hi @Andrew_Morgan. I am not using the Legacy Sync. I’ve been using Realm for a while and have been holding out for MongoDB Realm Sync, but have a few implementation questions.

I have a Log Object that has a uuid field that is a String and is the primary key. Should I rename the uuid field to _id or should I create another field for _id? Or do I create a new object type?

Next, how exactly do I go about copying all the old records to the new realm in a seamless end-user experience? Do I just open both realms at the same time and copy each object individually?

Then how do I go about making the default realm the synced realm, so I can just use let realm = Realm() throughout my iOS app

For your Log Object, renaming your uuid field to _id should work. _id can be a string or ObjectId.

I think your description of how to copy the objects makes sense.

TBH, I don’t tend to set the default Realm config. Instead, I open a synced realm and then the app uses a reference to that realm for transactions. This tutorial includes an example with asyncOpen: https://docs.mongodb.com/realm/tutorial/ios-swift/

Thanks @Andrew_Morgan. I’m going to give the copying a shot at some point and may have some more questions!

I built this app a while ago and I’m instantiating Realms all over the place. In fact, many of my view controllers have their own Realm instances. Is it a better practice to have a data store manager/singleton and use one instance throughout the app?

@Andrew_Morgan any advice would be helpful!

This is really a preferences question but in general I would say yes, it makes it a bit easier if you have your opening and closing of Realms in a single place like a singleton for when you want to do ancillary administrative tasks like compaction or ClientReset.

@Ian_Ward @Andrew_Morgan I am planning to migrate my users to realm sync and am going to use email auth (or custom JWT). However, not all users will have an account, so they will not be authorized. Is there a way to open a synced realm, but not authenticate? In other words, I want to be able to use the same code, etc. for authed and un-authed users, but only have data sync for authed users and unauthed users would still be able to use everything locally.

I think using a singleton and initializing with a local realm if there is no auth user and then if there is an auth user initialize with a synced realm.

Then if a local realm user logs in, copy the objects to the synced realm.

The only caveat is if a user logs out, then they will have no objects.

No a user must be authenticated in order to open a synced realm. You can use either anonymous authentication or use a dummy username/password where you login the user in the background in code if you want to open a sync realm without requiring the user to create an account or anything.

You could have two different methods exposed from your Realm Provider. If the user is not logged in then you can return a non-sync Realm, if there is a CurrentUser() != null then you can return a synced realm.

This thread has answered most of my questions about migrating from Local Realm to Realm Sync, but I’d like to confirm if the following approach will work:

My audio app will use a local realm and allow users to create an account later if they want their app data accessible from multiple devices. The app is also frequently used in Airplane mode so I also have to ensure that whether they’re logged in or not the app is always functional.

Is this possible:

  • The app comes with 2 Local-Realms and 1 Sync-Realm.
    • 1 Local-Realm, call it Local-Realm-App, contains all the app metadata and content and will remain local forever. Keeping this local ensures that the app is always functional whether online or offline.
    • 1 Local-Realm, call it Local-Realm-User, contains user preferences and playlists the user creates.
    • 1 Sync-Realm, call it Sync-Realm-User, that will be used for user preferences if they register an account.
  • By default, all users start with Local-Realm-User.
  • If they choose to create an account and become a registered user I copy the user preferences/playlist objects from Local-Realm-User to Sync-Realm-User, but I don’t delete the Local-Realm-User, I keep it as a fallback if a registered user isn’t logged in and their device isn’t connected, or if they decide to keep the app but cancel their account.
  • If a registered user opens the app in Airplane mode and the auth token has expired instead of asking them to go online and login, the app just runs off the Local-Realm-User. I recognize that Local-Realm-User may be out of date at that point, but the app will be functional. The UI will let them know that some data may be out of date and they need to login to see their up-to-date preferences.
  • For users that have registered, I may also periodically copy all data from Sync-Realm-User to Local-Realm-User so that my fallback realm is more up-to-date should it ever be needed.

Is this approach possible? Is there a better approach you would suggest to address this scenario?