Docs Menu

Docs HomeRealm

Relationships & Embedded Objects - React Native SDK

On this page

  • Relationships
  • To-One Relationship
  • To-Many Relationship
  • Inverse Relationship
  • Embedded Objects
  • Realm Object Models
  • JSON Schema

Realm allows you to define explicit relationships between the types of objects in an App. A relationship is an object property that references another Realm object type. You can define relationships by setting an object's property to another object type in the property schema.

Relationships are direct references to other objects in a realm. You don't need bridge tables or joins to define a relationship like you would in a relational database. Instead you can access related objects by reading and writing to the property that defines the relationship.

Realm Database executes read operations lazily as they come in. Querying a relationship is just as performant as reading a regular property.

There are three primary types of relationships between objects:

Note

Realm vs Other Databases

Objects often contain direct references to other objects. When working with objects and references, you often copy from database storage into application memory. This situation leaves the developer with a choice of what to copy into memory:

  • You can copy the entire referenced object ahead of time. This means that all referenced data is always available quickly, but can use up a lot of resources. Depending on the amount of available memory this may not be viable.

  • You can copy only a foreign key value for each object ahead of time that you can use to query the full object if it's needed. These referenced lookups are memory-efficient. However, they require more query code and too many lookups can slow your application down.

Realm's query architecture avoids the tradeoff between memory usage and computational overhead. Instead, Realm queries can directly reference related objects and their properties on disk.

A to-one relationship means that an object is related to no more than one other object in an object schema. To define a to-one relationship, specify the property type as the related Realm object type.

Example

An application could use the following object schemas to indicate that a Person may own a single Dog:

const Person = {
name: "Person",
properties: {
name: "string",
birthdate: "date",
dog: "Dog?"
}
};
const Dog = {
name: "Dog",
properties: {
name: "string",
age: "int",
breed: "string?"
}
};

A to-many relationship means that an object is related in a specific way to multiple objects. To define a to-many relationship, specify a property where the type is a list or array of the related Realm object type in its object schema.

Example

An application could use the following object schemas to indicate that a Person may own multiple Dogs:

const Person = {
name: "Person",
properties: {
name: "string",
birthdate: "date",
dogs: "Dog[]"
}
};
const Dog = {
name: "Dog",
properties: {
name: "string",
age: "int",
breed: "string?"
}
};

An inverse relationship links an object back to any other objects that refer to it in a defined to-one or to-many relationship. Relationship definitions are unidirectional by default. You must explicitly define a property in the object's model as an inverse relationship.

For example, the to-many relationship "User has many Tasks" does not automatically create the inverse relationship "Task belongs to User". If you don't specify the inverse relationship in the object model, you need to run a separate query to look up the user assigned to a task.

To define an inverse relationship, define a linkingObjects property in your object model. linkingObjects specifies the object type and property name of the relationship that it inverts.

You cannot manually set the value of an inverse relationship property. Realm Database automatically updates implicit relationships whenever you add or remove a related object.

Example

An application could use the following object schemas to indicate:

  1. A User may be assigned many Tasks.

  2. Each Task should automatically keep track of which User it's assigned to.

The User object's tasks property is defined as a to-many relationship with Task objects. It contains all of a given user's assigned tasks.

The Task object's assignee property inverts this relationship. Assignee automatically updates to refer back to any User object that contains the Task in its tasks property.

You can dynamically retrieve an object with an inverse relationship without defining a linkingObjects type in its schema. Remove the linkingObjects type from your schema, so your schemas look like a standard to-many relationship. When you need to retrieve the linked object, call the Realm.Object.linkingObjects() query.

Example

In the following continuation from the inverse relationship example, we have removed the assignee field with type 'linkingObjects' from the Task schema. An application developer creates several users and task objects, and the application pushes the newly created tasks into a user's task field.

To find the user who owns a specific task object, the developer calls the task.linkingObjects() method and passes the "User" class name and "tasks" field as parameters.

An embedded object is a special type of Realm object that models complex data. They also map more naturally to the MongoDB document model. Embedded objects are similar to relationships, but provide additional constraints.

Realm treats each embedded object as nested data inside of a parent object. An embedded object inherits the lifecycle of its parent object. It cannot exist as an independent Realm object. This means that embedded objects cannot have a primary key. Realm also automatically deletes embedded objects if their parent object is deleted.

Tip

Embedded object types are reusable and composable

You can use the same embedded object type in multiple parent object types. You can also embed objects inside of other embedded objects. You can even recursively reference an embedded object type as an optional property in its own definition.

To specify that a Realm object model defines an embedded object, set embedded to true. Reference an embedded object type from parent object types as you would define a relationship:

const AddressSchema = {
name: "Address",
embedded: true, // default: false
properties: {
street: "string?",
city: "string?",
country: "string?",
postalCode: "string?",
},
};
const ContactSchema = {
name: "Contact",
primaryKey: "_id",
properties: {
_id: "objectId",
name: "string",
address: "Address", // Embed a single object
},
};
const BusinessSchema = {
name: "Business",
primaryKey: "_id",
properties: {
_id: "objectId",
name: "string",
addresses: { type: "list", objectType: "Address" }, // Embed an array of objects
},
};

Embedded objects map to embedded documents in the parent type's schema. This behavior differs from regular Realm objects, which map to their own MongoDB collection.

{
"title": "Contact",
"bsonType": "object",
"required": ["_id"],
"properties": {
"_id": { "bsonType": "objectId" },
"name": { "bsonType": "string" },
"address": {
"title": "Address",
"bsonType": "object",
"properties": {
"street": { "bsonType": "string" },
"city": { "bsonType": "string" },
"country": { "bsonType": "string" },
"postalCode": { "bsonType": "string" }
}
}
}
}
{
"title": "Business",
"bsonType": "object",
"required": ["_id", "name", "addresses"],
"properties": {
"_id": "objectId",
"name": { "bsonType": "string" },
"addresses": {
"bsonType": "array",
"items": {
"title": "Address",
"bsonType": "object",
"properties": {
"street": { "bsonType": "string" },
"city": { "bsonType": "string" },
"country": { "bsonType": "string" },
"postalCode": { "bsonType": "string" }
}
}
}
}
}
←  Write Transactions - React Native SDKSchema Versions & Migrations - React Native SDK →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.