What is MongoDB Realm

Realm is a database designed specifically for mobile. The main feature is good performance, easy to use. Realm has gained some popularity on mobile and is suitable for use in lightweight scenarios. With the development of App, more and more local data needs to be synchronized with the server. If the team develops by itself, it needs to formulate the format of the server-side database (different from the mobile database), the storage of the server-side database, and write a program for data synchronization with the server. Implementing this requirement can be a lot of work for a small team. If Realm also provides a database on the cloud, then provide a synchronization program. The need for data synchronization becomes very easy for small – and medium-sized developers. Realm launched Realm Platform, also known as Realm Cloud. Realm Platform also charges based on capacity.

We have an APP whose function is to drive the UAV for data collection, and a core requirement is to record a lot of hardware-related logs. If a drone acquisition mission fails, we want to have a log that can help us find out what went wrong. So we have a need for something like instant messaging. As soon as we found something like Realm Platform, we paid $20 a month to use it.

After a few months of using the Realm Platform, the reality is still pretty clunky, and there are some serious issues with it:

  • Data synchronization is not stable. Although also based on AWS, only the US and Singapore nodes are available. Because of some mysterious force, there is often a problem of data nodes not being connected (this is alleviated by scientific Internet access).
  • Server database access is lousy. There is no web backend to process data, and accessing data in the cloud with GraphQL is also buggy. Originally, I planned to make a web page to display data, but finally I found that I could only make an iPad version APP with the provided mobile terminal SDK.

In summary, the Realm mobile database works fine, and so does data synchronization. But accessing databases in the cloud was too high a hurdle for the small team at Realm.

MongoDB is a popular NoSQL database, which is mainly used on the server side. The cloud-based MongoDB Atlas was later launched. With the development of mobile Internet, MongoDB wants to develop a service on mobile terminal, which can synchronize data to MongoDB Atlas conveniently. MongoDB released a beta SDK for iOS at the time. I tried it out, and it was terrible.

MongoDB is probably more determined, I can not do my own I will see if there is a ready-made ME to buy one. And it did, and it hit it off with Realm. A little more than six months after the acquisition came the new MongoDB Realm. The mobile database is still Realm, and the local data access interface is almost the same. Data is synchronized to MongoDB Atlas using the Realm Sync program. In theory, this is a combination of strong players that complement each other’s weaknesses.

The biggest known drawback for us after the merger is the increased cost, which was $20 per month. Now that MongoDB Realm is a new service, MongoDB charges from $57 per month. Hopefully the price will drop in the future as this service matures.

Server configuration: Create Atlas

The first step is to create an instance in the cloud that can run the database:Get Started with Atlas. In this process, you can select the nodes and performance of the cluster:It’s important to note that we’re using Realm Sync to synchronize data, instancesThe MongoDB version must be greater than 4.4.With version 4.4, you’ll find that your cluster can only be dedicated machines, not shared machines, so the cost will start at $57 per month.

Create a Realm App

Go to the Realm TAB and click Create in the upper right corner to create a Realm App instance.Create a window to enter the name of the instance, select the cluster to link to:Once you have created a Realm App, you can see the App Id assigned to the instance and configure it (such as authorization and Schema).

Create a mobile data model

Once the server is configured, we can define the data model on the mobile. In order for the Model to support synchronization, there are a few more requirements than regular Realm Objects.

First, the name of the primary key must be _id and the type must be ObjectId, String, and Int. So if you’re already using a REALM database, you’ll need to change the data structure to support synchronization.

Second, you must define an attribute to be used as a Partition key to classify data (used in the following example)_partition). For example, some data can only be accessed by each user, some can be accessed by a group, and some can be completely public. You can do this by setting the corresponding_partitionMark data classification. In the background, you can configure different access permissions based on partition keys. For more information, please refer to:Partition Atlas Data into Realms.Here is a Swift based object definition:

class User: Object {
    @objc dynamic var _id: String = ""
    @objc dynamic var _partition: String = ""
    @objc dynamic var name: String = ""

    override static func primaryKey(a) -> String? {
        return "_id"}}Copy the code

Server data Model configuration

Sync will need to be enabled on the Sync page of the Realm Control panel. In the configuration options, you need to select the Atlas cluster for synchronization, the partition key name, and the read and write permission. For details about the configuration, seeDefine Sync Rules.Read and write permissions can be configured based on the partition key. Permission configuration For more in-depth requirements, please refer to this document:Define Sync Permissions.The server can configure the data model in two ways:

  • Configure the MongoDB document format schema on the server
  • After the data model is defined on the mobile side, the server starts developer mode, and Realm Sync automatically synchronizes the data model schema to the server side

Server Configuration

First select the Schema menu in the Realm Control panel, then select the cluster you want to store in Collections and click the create plus buttonIf it is a new data model, select create one immediately during Collection Name configuration. Because there is also data that the server already has and now needs to synchronize, there is also data that is now available.After creation, select collection and select Schema TAB to configure it in an edit box:Here is one of my schemas:

{
  "title": "BaseLog"."bsonType": "object"."required": [
    "_id"."_partition"."deviceId"."timestamp"]."properties": {
    "_id": {
      "bsonType": "objectId"
    },
    "_partition": {
      "bsonType": "string"
    },
    "deviceId": {
      "bsonType": "string"
    },
    "timestamp": {
      "bsonType": "double"}}}Copy the code

The Schema can also perform verification for different data types. For example, you can configure the maximum and minimum number of digits. If it is a text type, you can configure a regular expression that is valid. You can refer to Document Schemas for specific Schemas.

After the configuration is complete, click The Data Models TAB in the SDKs menu to view the corresponding Model definition. If this is the case, you can also copy the models to the mobile after defining the schema.If the data model has a large number of attributes, writing this many by hand is laborious and error-prone. Therefore, I recommend the following method of synchronization.

Synchronization after definition on the mobile end

To enable automatic schema synchronization on the mobile terminal, the procedure is simple. As long as Dev Mode is enabled on the server, the new schema will be automatically synchronized to the server after the App runs (after authorization is successful).

Mobile user authorization

Data synchronization requires that the mobile terminal is authorized correctly. The first step is to initialize the MongoDB Realm instance. After creating a Realm App on the server, you will get an app Id and use this Id to initialize:

let app = App(id: "REALM_APP_ID")
Copy the code

In the Realm Console you can configure which authorization channels are enabled:Instantiate a credential and call the login method to login:

let cred = Credentials.userAPIKey("uDGDFuIZ0vW7nH7p5Y")
app.login(credentials: cred) { (result) in
    switch result {
    case .failure(let error):
        // error 
    case .success(let user):
        // login success}}Copy the code

Read and write data

Data is written to the same realm as regular storage, and is automatically synchronized when written to the local database.

let task = Task(partition: self.partitionValue, name: textField.text ?? "New Task")
try! self.realm.write {
    self.realm.add(task)
}
Copy the code

Data is read in the same way as local data. Just keep an eye out for the subscription data change callback, which notifies the data consumer if a data set changes (the server has new data synchronized locally) :

let tasks = realm.objects(Task.self)

// Watch for changes. No special syntax required for synced realms.
// Retain notificationToken as long as you want to observe.
let notificationToken = tasks.observe { (changes) in
     print("Changed: \(changes)")}// Later, when done observing
notificationToken.invalidate()
Copy the code

It is important to remember to hold a notificationToken, and if a notificationToken is released, the updated closure is also reclaimed.

conclusion

Mobile terminals continue to use realm databases, and cloud data is stored in MongoDB, which greatly improves data processing in the cloud and makes up for the shortcomings of the original Realm Platform. From what I’ve seen over the past few months, the Realm team is actively maintaining it, and MongoDB itself is happy to see realm continue to improve.

As for the specific stability issue, it is not clear because it is a new service, but I am quite optimistic about the future development. Our logging service is currently moving to MongoDB Realm, and if all goes well more data synchronization will be done through MongoDB Realm in the future.