Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Change an Object Model - React Native SDK

On this page

  • Schema Version
  • Migrations
  • Add a Property
  • Delete a Property
  • Rename a Property
  • Modify a Property Type

Note

Modify Schema Properties of a Synced Realm

The following page demonstrates how to modify schema properties of a local realm. Learn how to modify schema properties of a synced realm.

When updating your object schema, you must increment the schema version and perform a migration.

If your schema update adds optional properties or removes properties, Realm can perform the migration automatically. You only need to increment the schemaVersion.

For more complex schema updates, you must also manually specify the migration logic in a migration function. This might include changes such as:

  • Adding required properties that must be populated with default values

  • Combining fields

  • Renaming a field

  • Changing a field's type

  • Converting from an object to an embedded object

Tip

Bypass Migration During Development

When developing or debugging your application, you may prefer to delete the realm instead of migrating it. Use the BaseConfiguration.deleteRealmIfMigrationNeeded property to delete the database automatically when a schema mismatch requires a migration.

Never release an app to production with this property set to true.

A schema version identifies the state of a realm schema at some point in time. Realm tracks the schema version of each realm and uses it to map the objects in each realm to the correct schema.

Schema versions are ascending integers you can include in the realm configuration. If a client application does not specify a version number, the realm defaults to version 0.

Important

Increment Versions Monotonically

Migrations must update a realm to a higher schema version. Realm throws an error if a client application uses a schema version that is lower than the realm's current version or if the specified schema version is the same as the realm's current version but includes a different schema.

A migration is a function that updates a realm and any objects it contains from one schema version to a newer version. Migrations allow you to change your object schemas over time to accommodate new features and refactors.

When you create a Configuration with a schema version greater than the realm's current version, Realm runs a migration function that you define. The function has access to the realm's version number and incrementally updates objects in the realm to conform to the new schema.

Realm automatically migrates certain changes, such as new and deleted properties, but does not automatically set values for new properties unless the updated object schema specifies a default value. You can define additional logic in the migration function to further customize property values.

To add a property to a schema, add the new property to the object's class and set a schemaVersion of the Configuration object.

Example

A realm using schema version 0, the default, has a Person object type with a firstName and lastName property. You decide to add an age property to the Person class.

To migrate the realm to conform to the updated Person schema, you set the realm's schema version in the Configuration to 1. Finally, pass the configuration object to the createRealmContext() method.

class Person extends Realm.Object {
static schema = {
name: 'Person',
properties: {
_id: 'string',
firstName: 'string',
lastName: 'string',
// add a new property, 'age' to the schema
age: 'int',
},
};
}
const config = {
schema: [Person],
// Increment the 'schemaVersion', since 'age' has been added to the schema.
// The initial schemaVersion is 0.
schemaVersion: 2,
};
// pass the configuration object with the updated 'schemaVersion' to
// createRealmContext()
const {RealmProvider} = createRealmContext(config);
class Person extends Realm.Object<Person> {
_id!: string;
firstName!: string;
lastName!: string;
age!: number;
static schema: ObjectSchema = {
name: 'Person',
properties: {
_id: 'string',
firstName: 'string',
lastName: 'string',
// add a new property, 'age' to the schema
age: 'int',
},
};
}
const config: Realm.Configuration = {
schema: [Person],
// Increment the 'schemaVersion', since 'age' has been added to the schema.
// The initial schemaVersion is 0.
schemaVersion: 2,
};
// pass the configuration object with the updated 'schemaVersion' to
// createRealmContext()
const {RealmProvider} = createRealmContext(config);

To delete a property from a schema, remove the property from the object's class and set a schemaVersion of the Configuration object. Deleting a property will not impact existing objects.

Example

A realm using schema version 0, the default, has a Person object type with a lastName property. You decide to remove the property from the schema.

To migrate the realm to conform to the updated Person schema, set the realm's schema version to 1 in the Configuration object. Finally, pass the configuration object to the createRealmContext() method.

class Person extends Realm.Object {
static schema = {
name: 'Person',
properties: {
_id: 'string',
firstName: 'string',
age: 'int',
},
};
}
const config = {
schema: [Person],
// Increment the 'schemaVersion', since 'lastName' has been removed from the schema.
// The initial schemaVersion is 0.
schemaVersion: 1,
};
// pass the configuration object with the updated 'schemaVersion' to createRealmContext()
const {RealmProvider} = createRealmContext(config);
class Person extends Realm.Object<Person> {
_id!: string;
firstName!: string;
age!: number;
static schema: ObjectSchema = {
name: 'Person',
properties: {
_id: 'string',
firstName: 'string',
age: 'int',
},
};
}
const config: Realm.Configuration = {
schema: [Person],
// Increment the 'schemaVersion', since 'lastName' has been removed from the schema.
// The initial schemaVersion is 0.
schemaVersion: 1,
};
// pass the configuration object with the updated 'schemaVersion' to createRealmContext()
const {RealmProvider} = createRealmContext(config);

To rename an object property, change the property name in the object schema and then create a realm configuration with an incremented schema version and a migration function that updates existing objects to use the new property name.

Migrations do not allow you to directly rename a property. Instead, you can create a new property with the updated name, copy the value from the old property, and then delete the old property.

Example

A realm using schema version 0, the default, has a Person object type. The original schema had a firstName and lastName field. You later decide that the Person class should use a combined fullName field and removes the separate firstName and lastName fields.

To migrate the realm to conform to the updated Person schema, create a Configuration object and set the realm's schema version to 1, and define a migration function that sets the value of fullName based on the existing firstName and lastName properties. Finally, pass the configuration object to the createRealmContext() method.

class Person extends Realm.Object {
static schema = {
name: 'Person',
properties: {
_id: 'string',
// rename the 'firstName' and 'lastName' property, to 'fullName'
// in the schema
fullName: 'string',
age: 'int',
},
};
}
const config = {
schema: [Person],
// Increment the 'schemaVersion', since 'fullName' has replaced
// 'firstName' and 'lastName' in the schema.
// The initial schemaVersion is 0.
schemaVersion: 1,
onMigration: (oldRealm, newRealm) => {
// only apply this change if upgrading schemaVersion
if (oldRealm.schemaVersion < 1) {
const oldObjects = oldRealm.objects(Person);
const newObjects = newRealm.objects(Person);
// loop through all objects and set the fullName property in the
// new schema
for (const objectIndex in oldObjects) {
const oldObject = oldObjects[objectIndex];
const newObject = newObjects[objectIndex];
newObject.fullName = `${oldObject.firstName} ${oldObject.lastName}`;
}
}
},
};
// pass the configuration object with the updated 'schemaVersion' and
// 'migration' function to createRealmContext()
const {RealmProvider} = createRealmContext(config);
class Person extends Realm.Object<Person> {
_id!: string;
fullName!: string;
age!: number;
static schema: ObjectSchema = {
name: 'Person',
properties: {
_id: 'string',
// rename the 'firstName' and 'lastName' property, to 'fullName'
// in the schema
fullName: 'string',
age: 'int',
},
};
}
class OldObjectModel extends Realm.Object<OldObjectModel> {
_id!: string;
firstName!: string;
lastName!: string;
age!: number;
static schema: ObjectSchema = {
name: 'Person',
properties: {
_id: 'string',
firstName: 'string',
lastName: 'string',
},
};
}
const config: Realm.Configuration = {
schema: [Person],
// Increment the 'schemaVersion', since 'fullName' has replaced
// 'firstName' and 'lastName' in the schema.
// The initial schemaVersion is 0.
schemaVersion: 1,
onMigration: (oldRealm: Realm, newRealm: Realm) => {
// only apply this change if upgrading schemaVersion
if (oldRealm.schemaVersion < 1) {
const oldObjects: Realm.Results<OldObjectModel> =
oldRealm.objects(OldObjectModel);
const newObjects: Realm.Results<Person> = newRealm.objects(Person);
// loop through all objects and set the fullName property in the
// new schema
for (const objectIndex in oldObjects) {
const oldObject = oldObjects[objectIndex];
const newObject = newObjects[objectIndex];
newObject.fullName = `${oldObject.firstName} ${oldObject.lastName}`;
}
}
},
};
// pass the configuration object with the updated 'schemaVersion' and
// 'migration' function to createRealmContext()
const {RealmProvider} = createRealmContext(config);

Important

Synced Realms

Synced realms only support non-breaking - also called additive - changes to ensure that older clients can sync with newer clients. Because full renames require you to delete the old property, you cannot rename a synchronized property without requiring a client reset. Instead, consider adding the renamed property without deleting the old property. Alternately, use mapTo to store data using the existing internal name, but let your code use a different name.

To modify a property's type, set the property type of the field that you wish to modify to the new data type. Then, set a schemaVersion, and a migration callback function of the Configuration object.

Note

Synchronized realms only support non-breaking changes to ensure that older clients can sync with newer clients. This means that synchronized realms do not support modifying the type of a property of a schema.

Example

A realm using schema version 0, the default, has a Person object type. The original schema had an _id with a property type of int. You later decide that the Person class's _id field should be of type ObjectId, and updates the schema.

To migrate the realm to conform to the updated Person schema, create a Configuration object and set the realm's schema version to 1, and define a migration function to convert the integer type to an Object ID type. Finally, pass the configuration object to the createRealmContext() method.

class Person extends Realm.Object {
static schema = {
name: 'Person',
properties: {
// update the data type of '_id' to be 'objectId' within the schema
_id: 'objectId',
firstName: 'string',
lastName: 'string',
},
};
}
const config = {
schema: [Person],
// Increment the 'schemaVersion', since the property type of '_id'
// has been modified.
// The initial schemaVersion is 0.
schemaVersion: 1,
onMigration: (oldRealm, newRealm) => {
if (oldRealm.schemaVersion < 1) {
const oldObjects = oldRealm.objects(Person);
const newObjects = newRealm.objects(Person);
// loop through all objects and set the _id property
// in the new schema
for (const objectIndex in oldObjects) {
const oldObject = oldObjects[objectIndex];
const newObject = newObjects[objectIndex];
newObject._id = new Realm.BSON.ObjectId(oldObject._id);
}
}
},
};
// Pass the configuration object with the updated
// 'schemaVersion' and 'migration' function to createRealmContext()
const {RealmProvider} = createRealmContext(config);
class Person extends Realm.Object<Person> {
_id!: Realm.BSON.ObjectId;
firstName!: string;
lastName!: string;
age!: number;
static schema: ObjectSchema = {
name: 'Person',
properties: {
// Update the data type of '_id' to be 'objectId' within the schema.
_id: 'objectId',
firstName: 'string',
lastName: 'string',
},
};
}
// `OldObjectModel` is only used for type injection for `oldRealm`. It is
// not related to the `Person` object model.
interface OldObjectModel {
_id: Realm.BSON.ObjectId;
firstName: string;
lastName: string;
age: number;
}
const config: Realm.Configuration = {
schema: [Person],
// Increment the 'schemaVersion', since the property type of '_id'
// has been modified.
// The initial schemaVersion is 0.
schemaVersion: 1,
onMigration: (oldRealm: Realm, newRealm: Realm) => {
if (oldRealm.schemaVersion < 1) {
const oldObjects: Realm.Results<OldObjectModel> =
oldRealm.objects(Person);
const newObjects: Realm.Results<Person> = newRealm.objects(Person);
// Loop through all objects and set the _id property
// in the new schema.
for (const objectIndex in oldObjects) {
const oldObject = oldObjects[objectIndex];
const newObject = newObjects[objectIndex];
newObject._id = new Realm.BSON.ObjectId(oldObject._id);
}
}
},
};
// Pass the configuration object with the updated
// 'schemaVersion' and 'migration' function to createRealmContext().
const {RealmProvider} = createRealmContext(config);

Back

Relationships & Embedded Objects