Quick Start - Node.js SDK
On this page
This page contains information to quickly get Realm integrated into your app.
If you haven't already, install the Realm Node.js SDK.
Import Realm
At the top of your source files where you want to use Realm, add the following line to import the SDK and the BSON library.
import Realm, { BSON } from "realm";
Define Your Object Model
Your application's object model defines the data that you can store within Realm.
To define a Realm object type, create a schema object that specifies the type's
name
and properties
. The type name must be unique among object types in
a realm. For details on how to define specific properties, see Define
Object Properties.
The following code shows how to define an object model for a Task
object. In this example:
The
primaryKey
is the_id
of typeint
. Another common type used for primary keys is ObjectId.The
name
field is required.The
status
andowner_id
fields are optional, denoted by the question mark immediately after the data type.
export class QuickstartTask extends Realm.Object { static schema = { name: "Task", properties: { _id: "objectId", name: "string", status: "string?", owner_id: "string?", }, primaryKey: "_id", }; }
export class QuickstartTask extends Realm.Object<Task> { _id!: BSON.ObjectID; name!: string; status?: string; owner_id?: string; static schema: ObjectSchema = { name: "Task", properties: { _id: "objectId", name: "string", status: "string?", owner_id: "string?", }, primaryKey: "_id", }; }
Open a Realm
To open a realm, pass a Realm.BaseConfiguration object to Realm.open().
const realm = await Realm.open({ schema: [QuickstartTask], });
Find, Sort, and Filter Objects
The following code demonstrates how to:
Query for all instances of the "Task" object type.
Filter the query to retrieve only the tasks that are "Open".
Sort the tasks by the name in an ascending order.
// Query for specific obect using primary key. const specificTask = realm.objectForPrimaryKey(QuickstartTask, testId); // Query realm for all instances of the "Task" type. const tasks = realm.objects(QuickstartTask); // Filter for all tasks with a status of "Open". const openTasks = tasks.filtered("status = 'Open'"); // Sort tasks by name in ascending order. const tasksByName = tasks.sorted("name");
Create, Modify, and Delete Realm Objects
Once you have opened a realm, you can create, modify, and delete objects in it. All write operations must occur within a write transaction.
const allTasks = realm.objects(QuickstartTask); // Add a couple of Tasks in a single, atomic transaction. realm.write(() => { realm.create(QuickstartTask, { _id: firstId, name: "go grocery shopping", status: "Open", }); realm.create(QuickstartTask, { _id: secondId, name: "go exercise", status: "Open", }); }); const task1 = allTasks.find( (task) => task._id.toString() == firstId.toString() ); const task2 = allTasks.find( (task) => task._id.toString() == secondId.toString() ); realm.write(() => { // Modify an object. task1!.status = "InProgress"; // Delete an object. realm.delete(task2!); });
Watch a Collection
You can watch a realm, collection, or object for changes by registering event handlers with the Realm.addListener() Object.addListener() Collection.addListener() methods.
Important
Order Matters
In collection notification handlers, always apply changes in the following order: deletions, insertions, then modifications. Handling insertions before deletions may result in unexpected behavior.
In the following example, an application developer watches for changes to the
Task
collection.
// Define the collection notification listener. const listener = (tasks, changes) => { // Update UI in response to deleted objects. changes.deletions.forEach((index) => { // Deleted objects cannot be accessed directly, // but we can update a UI list, etc. knowing the index. console.log(`A task was deleted at the ${index} index.`); // ... }); // Update UI in response to inserted objects. changes.insertions.forEach((index) => { const insertedTasks = tasks[index]; console.log(`insertedTasks: ${JSON.stringify(insertedTasks, null, 2)}`); // ... }); // Update UI in response to modified objects. // `newModifications` contains an index to the modified object's position // in the collection after all deletions and insertions have been applied. changes.newModifications.forEach((index) => { const modifiedTask = tasks[index]; console.log(`modifiedTask: ${JSON.stringify(modifiedTask, null, 2)}`); // ... }); }; // Observe collection notifications. tasks.addListener(listener);
// Define the collection notification listener. //@ts-expect-error TYPEBUG: OrderedCollection is incorrectly implemented const listener: Realm.CollectionChangeCallback = ( tasks: Realm.OrderedCollection<QuickstartTask>, changes: Realm.CollectionChangeSet ) => { // Update UI in response to deleted objects. changes.deletions.forEach((index) => { // Deleted objects cannot be accessed directly, // but we can update a UI list, etc. knowing the index. console.log(`A task was deleted at the ${index} index.`); // ... }); // Update UI in response to inserted objects. changes.insertions.forEach((index) => { const insertedTasks = tasks[index]; console.log(`insertedTasks: ${JSON.stringify(insertedTasks, null, 2)}`); // ... }); // Update UI in response to modified objects. // `newModifications` contains an index to the modified object's position // in the collection after all deletions and insertions have been applied. changes.newModifications.forEach((index) => { const modifiedTask = tasks[index]; console.log(`modifiedTask: ${JSON.stringify(modifiedTask, null, 2)}`); // ... }); }; // Observe collection notifications. //@ts-expect-error TYPEBUG: OrderedCollection is incorrectly implemented tasks.addListener(listener);
Close a Realm
Call the realm.close() method when done with a realm instance to avoid memory leaks.
// Close the realm. realm.close();
Add Device Sync (Optional)
This section illustrates how to authenticate with an Anonymous User and open a Flexible Sync realm to sync data between devices.
Prerequisites
Anonymous authentication enabled in the App Services UI
Flexible Sync enabled with Development Mode on and an
owner_id
field in the Queryable Fields section
Initialize the App
To use App Services features, such as authentication and sync, you must first access your App Services App using your App ID. You can find your App ID in the App Services UI.
// Initialize your App. const app = new Realm.App({ id: "<yourAppId>", });
Authenticate a User
To authenticate and log in a user, call App.logIn(). When anonymous authentication is enabled, users can immediately log into your app without providing any identifying information:
// Initialize your App. const app = new Realm.App({ id: "<yourAppId>", }); // Authenticate an anonymous user. const anonymousUser = await app.logIn(Realm.Credentials.anonymous());
Define an Object Model
Object models for synced realms work the same way as local-only Realms. Define your object model just as you would for a local-only Realm.
export class QuickstartTask extends Realm.Object { static schema = { name: "Task", properties: { _id: "objectId", name: "string", status: "string?", owner_id: "string?", }, primaryKey: "_id", }; }
export class QuickstartTask extends Realm.Object<Task> { _id!: BSON.ObjectID; name!: string; status?: string; owner_id?: string; static schema: ObjectSchema = { name: "Task", properties: { _id: "objectId", name: "string", status: "string?", owner_id: "string?", }, primaryKey: "_id", }; }
Open a Synced Realm
After you have initialized your App, authenticated a user, and defined your object model, you can create a SyncConfiguration.
To open a Flexible Sync realm, call Realm.open().
Pass in a BaseConfiguration
object, which must include the sync
property defining a
SyncConfiguration object.
To use Flexible Sync, in the SyncConfiguration, you must include include a
user
and flexible: true
.
Additionally, you need at least one subscription before you can read from or write to the
realm. Use Configuration.sync.initialSubscriptions
to define the initial
subscription set when the Realm file is first opened.
// Initialize your App. const app = new Realm.App({ id: "<yourAppId>", }); // Authenticate an anonymous user. const anonymousUser = await app.logIn(Realm.Credentials.anonymous()); // Create a `SyncConfiguration` object. const config = { schema: [QuickstartTask], sync: { // Use the previously-authenticated anonymous user. user: anonymousUser, // Set flexible sync to true to enable sync. flexible: true, // Define initial subscriptions to start syncing data as soon as the // realm is opened. initialSubscriptions: { update: (subs, realm) => { subs.add( // Get objects that match your object model, then filter them by // the `owner_id` queryable field realm .objects(QuickstartTask) .filtered(`owner_id == "${anonymousUser.id}"`) ); }, }, }, }; const realm = await Realm.open(config);
// Initialize your App. const app = new Realm.App({ id: "<yourAppId>", }); // Authenticate an anonymous user. const anonymousUser = await app.logIn(Realm.Credentials.anonymous()); // Create a `SyncConfiguration` object. const config: Realm.Configuration = { schema: [QuickstartTask], sync: { // Use the previously-authenticated anonymous user. user: anonymousUser, // Set flexible sync to true to enable sync. flexible: true, // Define initial subscriptions to start syncing data as soon as the // realm is opened. initialSubscriptions: { update: (subs, realm) => { subs.add( // Get objects that match your object model, then filter them by // the `owner_id` queryable field realm .objects(QuickstartTask) .filtered(`owner_id == "${anonymousUser.id}"`) ); }, }, }, }; const realm = await Realm.open(config);
The syntax to read, write, and watch for changes on a synced realm is identical to the syntax for non-synced realms above. While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.