Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Define a Realm Object Model - React Native SDK

On this page

  • Define an Object Type
  • Supported Property Types
  • Define Object Properties
  • Declare an Optional Property
  • Declare a Primary Key
  • Index a Property
  • Set a Full-Text Search Index
  • Set a Default Property Value
  • Remap a Property
  • Define an Asymmetric Object
  • Define Unstructured Data
  • TypeScript and Required Properties

To define a Realm object type, create a class that extends Realm.Object. Define the type's name and properties in a static property called schema. The type's name must be unique among object types in a realm.

class Book extends Realm.Object {
static schema = {
name: 'Book',
properties: {
name: {type: 'string', indexed: true},
price: 'int?',
},
};
}
class Book extends Realm.Object<Book> {
name!: string;
price?: number;
static schema: ObjectSchema = {
name: 'Book',
properties: {
name: {type: 'string', indexed: true},
price: 'int?',
},
};
}

Then you can pass the class itself to the schema property of the Configuration object when opening a realm.

Every property in a Realm object has a strongly defined data type. A property's type can be a primitive data type or an object type defined in the same realm. The type also specifies whether the property contains a single value or a list of values.

To specify that a field contains a list of a primitive value type, append [] to the type name.

For a list of supported property types, see Property Types

To define a property for an object type, create a key-value pair representing the name and data type of the property under the properties field.

The following schema defines a Car type that has these properties: _id make, model, and miles.

To mark a property as optional, use object syntax and set optional to true. You can also use a simplified syntax: append a question mark ? to the type. This is best-suited to basic types. You should use the more specific object syntax for more complicated types.

In the following example of a Person class, the age and birthday properties are both optional.

class Person extends Realm.Object<Person> {
name!: string;
age?: number;
birthday?: Date;
static schema: ObjectSchema = {
name: 'Person',
properties: {
name: 'string',
age: {
type: 'int',
optional: true,
},
// You can use a simplified syntax instead. For
// more complicated types, use the object syntax.
birthday: 'date?',
},
};
}

To specify a property as an object type's primary key, set the schema's primaryKey field to the property name.

Note

A primary key is a property that uniquely identifies an object. Realm automatically indexes primary key properties, which allows you to read and modify objects based on their primary key efficiently.

If an object type has a primary key, then all objects of that type must include the primary key property with a unique value among objects of the same type in a realm. An object type can have only one primary key. You cannot change the primary key property for an object type after any object of that type is added to a realm, and you cannot modify an object's primary key value.

In the following example of a Task class, we specify the _id property as the primary key.

1class Task extends Realm.Object {
2 static schema = {
3 name: 'Task',
4 properties: {
5 _id: 'int',
6 name: 'string',
7 priority: 'int?',
8 progressMinutes: 'int?',
9 assignee: 'Person?',
10 },
11 primaryKey: '_id',
12 };
13}
1class Task extends Realm.Object<Task> {
2 _id!: number;
3 name!: string;
4 priority?: number;
5 progressMinutes?: number;
6 assignee?: Person;
7 age?: number;
8
9 static schema: ObjectSchema = {
10 name: 'Task',
11 properties: {
12 _id: 'int',
13 name: 'string',
14 priority: 'int?',
15 progressMinutes: 'int',
16 assignee: 'Person?',
17 },
18 primaryKey: '_id',
19 };
20}

If you frequently run read operations based on a specific property, you can index the property to optimize performance. Realm supports indexing for string, integer, boolean, Date, UUID, and ObjectId properties.

Note

An index significantly increases the speed of certain read operations at the cost of slightly slower write times and additional storage and memory overhead. Realm stores indexes on disk, which makes your realm files larger. Each index entry is a minimum of 12 bytes. The ordering of the index entries supports efficient equality matches and range-based query operations.

To index a given property, set the property's indexed field to true.

In the following example of a Book class, we define an index on the name property.

1class Book extends Realm.Object {
2 static schema = {
3 name: 'Book',
4 properties: {
5 name: {type: 'string', indexed: true},
6 price: 'int?',
7 },
8 };
9}
1class Book extends Realm.Object<Book> {
2 name!: string;
3 price?: number;
4
5 static schema: ObjectSchema = {
6 name: 'Book',
7 properties: {
8 name: {type: 'string', indexed: true},
9 price: 'int?',
10 },
11 };
12}

In addition to standard indexes, Realm also supports Full-Text Search (FTS) indexes on string properties. While you can query a string field with or without a standard index, an FTS index enables searching for multiple words and phrases and excluding others.

For more information on querying FTS indexes, see Filter with Full-Text Search.

To create an FTS index, set the indexed type to 'full-text'. This enables full-text queries on the property. In the following example, we set the indexed type for the name property to 'full-text':

class Book extends Realm.Object<Book> {
name!: string;
price?: number;
static schema: ObjectSchema = {
name: 'Book',
properties: {
name: {type: 'string', indexed: 'full-text'},
price: 'int?',
},
};
}

To define a default value, set the value of the property to an object with a type field and a default field.

In the following example of a Car class, we define a miles property with a default value of 0.

New in version 11.1.0.

In Realm.js v11.1.0 and later, you can use a function to define a dynamic default value, like the timestamp property in the example below.

1class Car extends Realm.Object {
2 static schema = {
3 name: 'Car',
4 properties: {
5 make: 'string',
6 model: 'string',
7 miles: {type: 'int', default: 0},
8 timestamp: {
9 type: 'int',
10 default: () => Math.round(new Date().getTime() / 1000),
11 },
12 },
13 };
14}
1class Car extends Realm.Object {
2 make!: string;
3 model!: string;
4 miles: number = 0;
5 timestamp: number = Math.round(new Date().getTime() / 1000);
6
7 static schema: ObjectSchema = {
8 name: 'Car',
9 properties: {
10 make: 'string',
11 model: 'string',
12 miles: {type: 'int', default: 0},
13 timestamp: {
14 type: 'int',
15 default: () => Math.round(new Date().getTime() / 1000),
16 },
17 },
18 };
19}

To use a different property name in your code than is stored in Realm, set mapTo to the name of the property as it appears in your code.

In the following example of an Employee class, we remap the first_name property to firstName.

1class Employee extends Realm.Object {
2 static schema = {
3 name: 'Employee',
4 properties: {
5 _id: 'string',
6 first_name: {type: 'string', mapTo: 'firstName'},
7 },
8 primaryKey: '_id',
9 };
10}
1class Employee extends Realm.Object {
2 _id!: string;
3 first_name!: string;
4
5 static schema: ObjectSchema = {
6 name: 'Employee',
7 properties: {
8 _id: 'string',
9 first_name: {type: 'string', mapTo: 'firstName'},
10 },
11 primaryKey: '_id',
12 };
13}

If you are using Flexible Sync and need to sync a collection unidirectionally from your device to your Atlas database, you can set the asymmetric property on your object schema.

class WeatherSensor extends Realm.Object {
static schema = {
name: 'WeatherSensor',
// sync WeatherSensor objects one way from your device
// to your Atlas database.
asymmetric: true,
primaryKey: '_id',
properties: {
_id: 'objectId',
deviceId: 'string',
temperatureInFahrenheit: 'int',
barometricPressureInHg: 'float',
windSpeedInMph: 'float',
},
};
}
class WeatherSensor extends Realm.Object<WeatherSensor> {
_id!: Realm.BSON.ObjectId;
deviceId!: string;
temperatureInFahrenheit!: number;
barometricPressureInHg!: number;
windSpeedInMph!: number;
static schema: ObjectSchema = {
name: 'WeatherSensor',
// sync WeatherSensor objects one way from your device
// to your Atlas database.
asymmetric: true,
primaryKey: '_id',
properties: {
_id: 'objectId',
deviceId: 'string',
temperatureInFahrenheit: 'int',
barometricPressureInHg: 'float',
windSpeedInMph: 'float',
},
};
}

Changed in version realm@12.2.1.

In JS SDK versions 12.2.0 and earlier, you cannot link from asymmetric objects to Realm.Object types. In SDK versions 12.2.1 and later, asymmetric objects can link to Realm.Object types in addition to embedded objects.

Note

Attempting to Read Asymmetric Objects

Asymmetric objects cannot be read. If you attempt to query an asymmetric object, you will get the following error: "Error: You cannot query an asymmetric class.".

To learn more about Data Ingest, read Stream Data to Atlas.

New in version realm@12.9.0.

Starting in JS SDK version 12.9.0, you can store collections of mixed data within a mixed property. You can use this feature to model complex data structures, such as JSON or MongoDB documents, without having to define a strict data model.

Unstructured data is data that doesn't easily conform to an expected schema, making it difficult or impractical to model to individual data classes. For example, your app might have highly variable data or dynamic data whose structure is unknown at runtime.

Storing collections in a mixed property offers flexibility without sacrificing functionality, including performant synchronization when using Device Sync. And you can work with them the same way you would a non-mixed collection:

  • You can nest mixed collections up to 100 levels.

  • You can query on and react to changes on mixed collections.

  • You can find and update individual mixed collection elements.

However, storing data in mixed collections is less performant than using a structured schema or serializing JSON blobs into a single string property.

To model unstructured data in your app, define the appropriate properties in your schema as mixed types. You can then set these mixed properties as a list or a dictionary collection of mixed elements. Note that a mixed property cannot hold a set or an embedded object.

Tip

  • Use a map of mixed data types when the type is unknown but each value will have a unique identifier.

  • Use a list of mixed data types when the type is unknown but the order of objects is meaningful.

We recommend creating Realm objects with Realm.create(), but you can also use the new operator for your object model's class.

If you use new, you must add your class as a generic, along with any required properties, when extending Realm.Object. This enables full TypeScript support for your object model, including type errors when required fields are not defined.

class Book extends Realm.Object<Book, 'name' | 'store'> {
name!: string;
store!: string;
price?: number;
static schema: ObjectSchema = {
name: 'Book',
properties: {
name: {type: 'string', indexed: true},
store: 'string',
price: 'int?',
},
};
}

Back

Model Data