Mark Thien
Mark Thien

Reputation: 1167

Realm react native schema versioning

I have the following 2 schemas in realm.js file

    class Bill extends Realm.Object {}
        Bill.schema = {
          name: 'Bill',
          primaryKey: 'id',
          properties: {
            id: { type: 'string', indexed: true },
            year: 'int',
            month: 'int',
            description: 'string',
            dateCreated: 'int',
        }
    };

    class User extends Realm.Object {}
        User.schema = {
          name: 'User',
          primaryKey: 'id',
          properties: {
            id: 'string',
            name: 'string?',
            email: 'string?'
          }
    };

 const realm = new Realm({schema: [Bill, User]}); 

 export default realm;

this works perfectly when I first release my app to AppStore or PlayStore. I need to change both schema and release to AppStore or PlayStore again and I need to handle both new installation or update of my app where the schema change to following

    class Bill extends Realm.Object {}
        Bill.schema = {
          name: 'Bill',
          primaryKey: 'id',
          properties: {
            id: { type: 'string', indexed: true },
            year: 'int',
            month: 'int',
            description: 'string',
            dateCreated: 'int',
            dateDeleted: 'int',
        }
    };

    class User extends Realm.Object {}
        User.schema = {
          name: 'User',
          primaryKey: 'id',
          properties: {
            id: 'string',
            name: 'string?',
            email: 'string?',
            photoUrl: 'string?',
          }
    };

by adding one more field in each schema.

So how should I configure my realm schema version?

Should I configure like below:

const realm = new Realm([
              {schema: Bill, schemaVersion: 1}, 
              {schema: User, schemaVersion: 1}
            ]);

But this may crash for new installation.

Upvotes: -1

Views: 1971

Answers (2)

Alvaro Carvalho
Alvaro Carvalho

Reputation: 83

I understand this is an old question and Realm has greatly evolved since then, but for anyone coming fresh and having trouble defining schemas or migrations, Realm in react native should be defined within a <RealmProvider />, and it should receive at least props for the schema configuration and schemaVersion.

Here's how I declared my Realm in my React Native app.

On App.js I define the RealmProvider as such:

<RealmProvider {...realmConfig} deleteRealmIfMigrationNeeded={false}>
    //other components, Router, etc
</RealmProvider>

Explanation:

deleteRealmIfMigrationNeeded: This could be useful when in development because it ensures your realm is wiped clean whenever you change your schema(s). You should definitely leave this as false when in production, otherwise you'll risk losing the entire database.

realmConfig is an object that receives an array of schema and a schemaVersion, like such:

// import User, Bill

const schemas = [
    User.schema, // notice you pass only the schema to the array
    Bill.schema, // not the entire model/entity
]

export const realmConfig = {
    schema: schemas,
    schemaVersion: 1 // this could be any positive integer, but it MUST be incremented every time there is a schema change, even if you don't need a migration function

}

So notice that the realm config for the entire Realm takes only an array of Schemas, not separate objects for each model, and the schemaVersion is Realm scoped, not schema scoped. You have one specific schemaVersion for you entire Realm instance. You could definitely add more Realm instances and manage those manually, but having one instance is very nice as you get to use all the custom hooks provided by @realm/react.

I hope this helps!

Upvotes: 1

user28434&#39;mstep
user28434&#39;mstep

Reputation: 6600

You should set global schemaVersion for all database, not for each model. And perform migrations to the current version, like it's described in the docs:

You define a migration and the associated schema version by updating the schemaVersion and defining an optional migration function. Your migration function provides any logic needed to convert data models from previous schemas to the new schema. When opening a Realm the migration function will be applied to update the Realm to the given schema version only if a migration is needed.

If no migration function is supplied then any new properties an automatically added and old properties are removed from the database when updating to the new schemaVersion. If you need to update old or populate new properties when upgrading your version you can do this in the migration function. For example, suppose we want to migrate the Person model declared earlier. You can populate the name property of the new schema using the old firstName and lastName properties:

Realm.open({
  schema: [PersonSchema],
  schemaVersion: 1,
  migration: (oldRealm, newRealm) => {
    // only apply this change if upgrading to schemaVersion 1
    if (oldRealm.schemaVersion < 1) {
      const oldObjects = oldRealm.objects('Person');
      const newObjects = newRealm.objects('Person');

      // loop through all objects and set the name property in the new schema
      for (let i = 0; i < oldObjects.length; i++) {
        newObjects[i].name = oldObjects[i].firstName + ' ' + oldObjects[i].lastName;
      }
    }
  }
}).then(realm => {
  const fullName = realm.objects('Person')[0].name;
});

Once the migration is successfully completed the Realm and all of its objects can be accessed as usual by your app.

Upvotes: 0

Related Questions