Migrating from Legacy Realm Sync to MongoDB Realm Guide

Hey Folks,

I know a bunch of you have been looking for a guide on how to migrate from the old versions of Realm Object Server and Realm Cloud to MongoDB Realm. We’ve put together a guide here -

We would be interested to hear any and all feedback and how we can improve this doc over time.

-Ian

3 Likes

Great guide! That will be super helpful to a lot of developers.

Q: Is what’s laid out in the guide only applicable to working with Realm in the cloud? Or is it a general design pattern for even local (non-cloud) Realms? e.g. should local only apps include a _partitionKey? and should we be using ObjectId.generate() instead of UUID().uuidString?

Q:
In the Guide

Also, your new _id must be either an ObjectId, a String, or an Int.

Docs - probably just need to add “Int” assuming that’s allowable

A primary key is a String or ObjectId property that uniquely identifies an object.

and a question about primary keys:

In the Guide

The first thing you will need to do is convert your primary keys on your Realm Objects from your previous Primary Key field name to the required primary key of all MongoDB documents; which is _id

Docs

If an object type has a primary key, then all instances of that type must include the primary key

So two questions:

  1. In one case it sounds required, the other case sounds optional if an object instead of required. Is it required?

  2. It sounds like the primary key var must be named _id is that correct?

If every object is required to have _id, the docs should be updated to match

Object Customization

  • primaryKey()

Override this method to specify the name of a property to be used as the primary key.

Only properties of types String and Int can be designated as the primary key.

2 Likes

Also, in the guide all asynchronous calls are not handled correctly. eg anything like this

app.login(credentials: creds) { (user, error) in

No longer works after v10.0.0-rc.2 as they now appear to return a single result object

  • All Swift callbacks for asynchronous operations which can fail are now passed a Result<Value, Error> parameter instead of two separate Value? and Error? parameters.

So it looks like this

app.login(credentials: creds) { result in

Not sure why that change was made - it broke all of my error handling. Can we have an example of how that should be properly implemented?

IMO Result is too close to the existing Results object so it should have been named something else, but that’s me. :wink:

Edit: I believe the intended implementation is something like this?

switch result {
   case .success(let realm):
      //do something with realm
   case .failure(let error):
      print(error.localizedDescription)
}
1 Like

Hey Jay, thanks for the comments. This guide is just for legacy Realm Sync users - non-sync users are not affected. The primary key _id field is only required for sync users, the docs are allowing ambiguity for non-sync users since there is no such requirement - we are working to split our docs right now to make it clear what is sync and what is non-sync. Stay tuned.

The Swift team did get a last minute change in for 10.0 that used Result in callbacks - this was to make our APIs more “swifty” since this is a pretty standard design pattern. Result is a builtin type and you don’t actually have to declare anything as a result. The Result/Results thing is pretty unfortunate, but I don’t really know what we can do about the standard library picking a name very similar to a name we were already using. We are updating the docs right now to use this new syntax and I’ve already updated the migration guide. Here is a code block for you in the meantime -

let email = "skroob@example.com"
let password = "12345"
app.login(credentials: Credentials.emailPassword(email: email, password: password)) { result in
  DispatchQueue.main.async {
   switch result {
   case .success(let realm):
      //do something with realm
   case .failure(let error):
      print(error.localizedDescription)
  }
}
2 Likes

7 posts were split to a new topic: Migrating app using both Android & .Net SDKs from Realm Cloud to MongoDB Realm

Having a Realm Cloud productions, this new beast feels overly complex, and fragile. It is not the migration I was hoping for.

2 Likes

Is .Net SDK for MongoDB Realm ready? I found the docs but seems not working with latest Realm nuget package.

Yes you can use .NET - what are you running into?

The newly introduced Realm App Interface is not found.
I’ve imported “Realms” namespace and Intellisense cannot resolve.
I’ve tried .Net 4.7.2 (my original project for Realm Cloud), .Net core and standard
The latest nuget package I found is Realm 5.1.2

@Sing_Leung You need a 10.0+ version of RealmDotNet https://docs.mongodb.com/realm/dotnet/install/#dotnet-install

@Ian_Ward

I run into another error when building:
Error Could not copy the file “…\packages\Realm.10.0.0-beta.1\runtimes\win81-x64\native\realm-wrappers.dll” because it was not found.
Error Could not copy the file “…\packages\Realm.10.0.0-beta.1\runtimes\win81-x86\native\realm-wrappers.dll” because it was not found.

I’m on Win10 and VS Community 2019
the folders I have in the \packages\Realm.10.0.0-beta.1\runtimes are
win10*
win*

there is no win81* folders

@Ian_Ward

Are _partition properties automatically populated when adding new realm objects to realm ? Or do I need to do this manually on every object creation on the realm client ?

@timah You don’t have to set them in your client-side schema - it will be inferred from what you set-up as the partitionKey field on the server side and what value you open the realm with via the client-side API call. It should automatically inject this value when writing to Atlas. That being said, sometimes it helps to have the partitionKey be explicitly defined client side for readability.

Brilliant. It makes perfect sense. Thanks.

@Jay That text is for the server-side MongoDB Atlas implementation, particularly as it pertains to initial sync. In MongoDB every document you want to sync must have a partitionKey and it must have a valid value, ie. a value that conforms to your configuration (so you couldn’t have a bool for partitionKey which you specified as string).

The question I was answering for @timah was regarding if the partitionKey field is required in the client side code, ie Swift Realm code, which it is not, because sync will automatically add that value and field to the document in MongoDB when it syncs.

@Ian_Ward. For whatever reason I was under the impression that a _partitionKey was a required property within Swift Realm Class models. Now that I re-read the documentation and the migration guide, the This field is critically important is only in relation to migrating from ROS to Mongo.

So, adding a partitionKey property in Swift Realm Objects is not required - the server will add that property (field) and value upon syncing as you mentioned.

@Jay

Thanks. Yes, I know the docs very well by now. I’m just surprised that we don’t have some sort of “auto partition mode” where the _partition field is automatically filled with the ditto value requested by the SyncConfiguration.

@Jay The field used to be required, in the beta versions of the 10.0 SDKs, but with GA of 10.0 SDKs the field is now auto-pulled from the SyncConfiguration

Thanks @Ian_Ward I thought I had read that somewhere.

@timah

Actually, I believe that’s exactly what happens. If you have a class

class MyClass: Object {
   @objc dynamic var _id: .....
   @objc dynamic var _partitionKey = ""

the _partitionKey value will be auto-populated with the partition used when fetching the realm

Expanding on that, as Ian said above, the _partitionKey can be completly omitted from your Swift Realm classes. One less property to deal with.