Create Objects
On this page
- Write Transactions
- Managed and Unmanaged Objects
- Create Object Methods
- Create One Object
- Create Multiple Objects
- Create or Update an Object (Upsert)
- Initialize Objects with a Value
- Create Objects from JSON
- Create an Unmanaged Copy of an Object
- Copy an Object to Another Database
- Create Objects in the Background
This page describes the concepts of write transactions and managed objects in a database, then explains how to create and persist a new object to a local or synced database using Atlas Device SDK. To learn more about object models and how to define them, refer to Define an SDK Object Model.
You can create objects whose object type is managed by the database instance. For more information, refer to:
With Sync: Configure & Open a Synced Database
Without Sync: Configure & Open a Database File
Note
Write to a Synced Database
The syntax to write a new object to the database is the same for a local or a synced database. However, there are additional considerations that determine whether the write operation in a synced database is successful. For more information, refer to Write Data to a Synced Database.
Write Transactions
The Atlas Device SDK persistence layer handles writes in terms of transactions. All writes must happen within a transaction. A transaction is a list of read and write operations that the database treats as a single indivisible operation: either all of the operations succeed or none of the operations in the transaction take effect.
The SDK represents each transaction as a callback function that contains zero or more read and write operations. To run a transaction, you define a transaction callback and pass it to one of the database's write methods. Within this callback, you can access a database instance and then create, read, update, and delete objects within the database.
A database file allows only one open write transaction at a time. The SDK blocks other writes on other threads until the open transaction on the database file is complete. This means there is never a race condition when reading values from the database within a transaction.
When you are done with your transaction, the SDK either commits it or cancels it:
When the SDK commits a write transaction, it writes all changes to disk. For synced databases, the SDK then queues the change for synchronization with the backend.
When the SDK cancels a write transaction or an operation in the transaction causes an error, it discards all changes.
Managed and Unmanaged Objects
The SDK's APIs may refer to objects as managed or unmanaged. When you create an object with the SDK, it is unmanaged until it is added to the database, which creates a managed instance.
Managed objects are SDK objects that persist in a database instance. Managed objects can only be accessed from an open database file. They can be updated with changes within write transactions as long as that database remains open. Managed objects are tied to the database instance from which they originated and cannot be directly written to another database. However, some of the SDKs supply a method to copy managed objects from one database file to another. Refer to the Copy an Object to Another Database section on this page.
You can use the SDK's APIs with managed objects. For example, managed objects can have relationships with other objects and you can observe them for changes. You can also create an unmanaged copy of a managed object. Refer to the Create an Unmanaged Copy of an Object or Collection section on this page.
Unmanaged objects are SDK objects that behave like normal objects, but they are not persisted in the database. All SDK objects are unmanaged until you add them to a database within a write transaction. You cannot use the SDK's APIs with unmanaged objects or observe them for changes.
Create Object Methods
The SDK provides a variety of methods to create objects and perform write operations.
Create One Object
To create a new object and persist it to the database:
Open a write transaction with Realm.write() function.
Instantiate an unmanaged object instance within the
realm
namespace.Move the unmanaged object instance into the database using the Realm.add() function.
When you move an object into a database, this consumes the object as an rvalue. You must use the managed object for any data access or observation. If you would like to immediately work with the object, return a managed version of the object.
Work with the persisted SDK object through the returned instance. Note that this does not apply to asymmetric objects, which are write-only. Once an asymmetric object is synced, it is deleted from the database. You cannot read, update, or delete an asymmetric object from the device.
Open a write transaction with the Realm.Write() or Realm.WriteAsync() methods. Prefer
WriteAsync()
to avoid blocking the UI, unless blocking the UI is desired.Instantiate an unmanaged object instance whose object model implements one of the SDK's object interfaces. For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the Realm.Add() method to persist the object data to the database.
Note that asymmetric objects are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
Open a write transaction with a Realm.write() or Realm.writeAsync() methods.
Instantiate an unmanaged object instance whose
RealmObject
model has been successfully created, generated, and imported into the file. For more information, refer to Define an SDK Object Model.Pass the unmanaged object instance to the Realm.add() method to persist the object data to the database. You can return managed objects from the write transaction block to observe or work with them immediately.
Note that asymmetric objects are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
Open a write transaction with the realm.executeTransaction() or realm.executeTransactionAsync() methods.
Instantiate an unmanaged object instance whose model subclasses RealmObject or implements the RealmModel interface. For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the realm.createObject() method or the createObjectFromJson() method to create an SDK object instance.
Open a write transaction with the Realm.write() method.
Instantiate an unmanaged object instance of your JavaScript class or a class that extends Realm.object. For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the Realm.create() method to persist the object data to the database. You can assign the new managed object to a variable or return it from the write transaction block to observe or work with it immediately.
Note that asymmetric objects are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
Open a write transaction with realm.write() or realm.writeBlocking().
Instantiate an unmanaged object instance with the class constructor. You can use an apply block to configure multiple properties at once.
Pass the unmanaged object instance to copyToRealm() to persist the object data to the database. This method returns a live managed instance of the object.
Important
Asymmetric Objects Use Insert()
Asymmetric objects are special write-only objects that do not persist to the database. They do not use
copyToRealm()
. Instead, you pass the asymmetric object instance to theinsert()
extension method within a write transaction. Refer to the Create an Asymmetric Object section on this page for more information.Work with the persisted SDK object through the returned instance. The live object is accessible until the write transaction completes. Note that this does not apply to asymmetric objects, which are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
Note
Frozen Objects
In Kotlin, objects returned from a write closure become frozen objects when the write transaction completes. For more information, refer to Live and Frozen Objects.
Open a write transaction with the realm.executeTransaction() or realm.executeTransactionAsync() methods.
Instantiate an unmanaged object instance whose model subclasses RealmObject or implements the RealmModel interface. For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the realm.createObject() method or the createObjectFromJson() method to create an SDK object instance.
Open a write transaction with the -[RLMRealm transactionWith:block] or the -[RLMRealm transactionWithoutNotifying:block:] methods.
Instantiate an unmanaged object instance of a class that subclasses one of:
For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the -[RLMRealm addObject:] method to persist the object data to the database.
Open a write transaction with the
Realm.write()
,``Realm.writeAsync()``, orRealm.asyncWrite()
methods.Instantiate an unmanaged object instance of a class that subclasses one of:
For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the Realm.create() or Realm.add() methods to persist the object data to the database.
Note that asymmetric objects are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
Open a write transaction with the Realm.write() method.
Instantiate an unmanaged object instance of a class that extends Realm.object. For more information, refer to Define an SDK Object Model.
Pass the unmanaged object instance to the Realm.create() method to persist the object data to the database. You can assign the new managed object to a variable or return it from the write transaction block to observe or work with it immediately.
Note that asymmetric objects are write-only. Once an asymmetric object is synced, it is deleted from the device database. You cannot read, update, or delete an asymmetric object from the device.
// Create an object using the `realm` namespace. auto dog = realm::Dog{.name = "Rex", .age = 1}; std::cout << "dog: " << dog.name << "\n"; // Open the database with compile-time schema checking. auto config = realm::db_config(); auto realm = realm::db(std::move(config)); // Persist your data in a write transaction // Optionally return the managed object to work with it immediately auto managedDog = realm.write([&] { return realm.add(std::move(dog)); });
var testItem = new Item { Name = "Do this thing", Status = ItemStatus.Open.ToString(), Assignee = "Aimee" }; await realm.WriteAsync(() => { realm.Add(testItem); }); // Or var testItem2 = await realm.WriteAsync(() => { return realm.Add<Item>(new Item { Name = "Do this thing, too", Status = ItemStatus.InProgress.ToString(), Assignee = "Satya" }); } );
final yoda = realm.write<Person>(() { return realm.add(Person(ObjectId(), 'Yoda')); });
realm.executeTransaction(r -> { // Instantiate the class using the factory function. Turtle turtle = r.createObject(Turtle.class, new ObjectId()); // Configure the instance. turtle.setName("Max"); // Create a TurtleEnthusiast with a primary key. ObjectId primaryKeyValue = new ObjectId(); TurtleEnthusiast turtleEnthusiast = r.createObject(TurtleEnthusiast.class, primaryKeyValue); });
// Declare the variable that will hold the dog instance. let dog; // Open a transaction. realm.write(() => { // Assign a newly-created instance to the variable. dog = realm.create("Dog", { name: "Max", age: 5 }); }); // use newly created dog object
// Open a write transaction realm.write { // Instantiate a new unmanaged Frog object val unmanagedFrog = Frog().apply { name = "Kermit" age = 42 owner = "Jim Henson" } assertFalse(unmanagedFrog.isManaged()) // Copy the object to realm to return a managed instance val managedFrog = copyToRealm(unmanagedFrog) assertTrue(managedFrog.isManaged()) // Work with the managed object ... }
realm.executeTransaction { r: Realm -> // Instantiate the class using the factory function. val turtle = r.createObject(Turtle::class.java, ObjectId()) // Configure the instance. turtle.name = "Max" // Create a TurtleEnthusiast with a primary key. val primaryKeyValue = ObjectId() val turtleEnthusiast = r.createObject( TurtleEnthusiast::class.java, primaryKeyValue ) }
// Get the default realm. // You only need to do this once per thread. RLMRealm *realm = [RLMRealm defaultRealm]; // Instantiate the class. Dog *dog = [[Dog alloc] init]; dog.name = @"Max"; dog.age = 5; // Open a thread-safe transaction. [realm transactionWithBlock:^() { // Add the instance to the realm. [realm addObject:dog]; }];
// Instantiate the class and set its values. let dog = Dog() dog.name = "Rex" dog.age = 10 // Get the default realm. You only need to do this once per thread. let realm = try! Realm() // Open a thread-safe transaction. try! realm.write { // Add the instance to the realm. realm.add(dog) }
// The documentation does not currently have this code example in TypeScript. // Please refer to the other languages or related pages for example code.
You can also upsert into a database using specific criteria. Refer to the Create or Update an Object (Upsert) section on this page.
Create Multiple Objects
Some of the SDKs provide a dedicated API to create multiple objects from a sequence or collection.
The SDK does not have a dedicated API to create multiple objects.
You can create multiple items in the database using the
Add
method. It takes a collection of standalone IRealmObject
instances to
add to the database.
To add multiple objects to a database, pass a list of multiple objects to Realm.addAll() inside a write transaction block.
The SDK does not have a dedicated API to create multiple objects.
The SDK does not have a dedicated API to create multiple objects.
The SDK does not have a dedicated API to create multiple objects.
The SDK does not have a dedicated API to create multiple objects.
You can create multiple items in the database using the -[RLMRealm addObjects:] method. It takes a collection of objects to add to the database.
You can create multiple items in the database using the add() method. It takes a sequence of objects to add to the database.
The SDK does not have a dedicated API to create multiple objects.
// The documentation does not currently have this code example in C++. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in C#. // Please refer to the other languages or related pages for example code.
realm.write(() { realm.addAll([ Person(ObjectId(), 'Figrin D\'an'), Person(ObjectId(), 'Greedo'), Person(ObjectId(), 'Toro') ]); });
// The Java SDK does not support this API.
// The Node.js SDK does not currently support this API.
// The Kotlin SDK does not currently support this API.
// The Java SDK does not support this API.
// The documentation does not currently have this code example in Objective-C. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Swift. // Please refer to the other languages or related pages for example code.
// This API is not currently available in TypeScript.
Create or Update an Object (Upsert)
An upsert is a write operation that either inserts a new object with a given primary key or updates an existing object that already has that primary key. We call this an upsert because it is an "update or insert" operation. This is useful when an object may or may not already exist, such as when bulk importing a dataset into an existing database. Upserting lets you update existing entries while adding any new entries.
This API is not currently supported in C++.
Upserting a document is the same as creating a new one, except you set the
optional update
parameter to true
. In this example, we create a new
Item
object with a unique Id
. We then insert an item with the
same id but a different Name
value. Because we have set the update
parameter to true
, the existing record is updated with the new name.
To upsert an object, call Realm.add()
with the optional update
flag set to true
inside a transaction block.
The following example demonstrates how to upsert an object with the SDK. We create a new turtle enthusiast named "Drew" and then update their name to "Andy" using insertOrUpdate():
realm.executeTransaction(r -> { ObjectId id = new ObjectId(); TurtleEnthusiast drew = new TurtleEnthusiast(); drew.set_id(id); drew.setName("Drew"); drew.setAge(25); // Add a new turtle enthusiast to the realm. Since nobody with this id // has been added yet, this adds the instance to the realm. r.insertOrUpdate(drew); TurtleEnthusiast andy = new TurtleEnthusiast(); andy.set_id(id); andy.setName("Andy"); andy.setAge(56); // Judging by the ID, it's the same turtle enthusiast, just with a different name. // As a result, you overwrite the original entry, renaming "Drew" to "Andy". r.insertOrUpdate(andy); });
You can also use copyToRealmOrUpdate() to
either create a new object based on a supplied object or update an
existing object with the same primary key value. Use the
CHECK_SAME_VALUES_BEFORE_SET
ImportFlag to only update fields
that are different in the supplied object.
The following example demonstrates how to insert an object or, if an object already exists with the same primary key, update only those fields that differ:
To upsert an object, call Realm.create()
with the update mode set to modified
. The operation either inserts a
new object with the given primary key or updates an existing object that
already has that primary key.
To upsert an object into a database, insert an object with a primary key using copyToRealm(), as you would when creating a new object. Pass an UpdatePolicy parameter to specify how the SDK should handle existing objects with the same primary key:
UpdatePolicy.ALL
: Update all properties on any existing objects identified with the same primary key.UpdatePolicy.ERROR
(default): Disallow updating existing objects and instead throw an exception if an object already exists with the same primary key. If you do not specify an update policy, the SDK uses this policy by default.
The following can occur depending on the update policy:
If no object exists that matches the primary key, the SDK creates the new object.
If an object with the same primary key already exists, the SDK either:
Updates all properties on any existing objects identified with the same primary key. Note that properties are marked as updated in change listeners, even if the property was updated to the same value.
Throws an exception indicating that an object already exists in the database.
In the following example, we attempt to insert a Frog
object with a
primary key that already exists in the database with UpdatePolicy.ALL
.
Then, we confirm the object is successfully upserted:
The following example demonstrates how to upsert an object with the SDK. We create a new turtle enthusiast named "Drew" and then update their name to "Andy" using insertOrUpdate():
realm.executeTransaction { r: Realm -> val id = ObjectId() val drew = TurtleEnthusiast() drew._id = id drew.name = "Drew" drew.age = 25 // Add a new turtle enthusiast to the realm. Since nobody with this id // has been added yet, this adds the instance to the realm. r.insertOrUpdate(drew) val andy = TurtleEnthusiast() andy._id = id andy.name = "Andy" andy.age = 56 // Judging by the ID, it's the same turtle enthusiast, just with a different name. // As a result, you overwrite the original entry, renaming "Drew" to "Andy". r.insertOrUpdate(andy) }
You can also use copyToRealmOrUpdate() to
either create a new object based on a supplied object or update an
existing object with the same primary key value. Use the
CHECK_SAME_VALUES_BEFORE_SET
ImportFlag to only update fields
that are different in the supplied object.
The following example demonstrates how to insert an object or, if an object already exists with the same primary key, update only those fields that differ:
To upsert an object, call -[RLMRealm addOrUpdateObject:].
RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ Person *jones = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Jones"}]; // Add a new person to the realm. Since nobody with ID 1234 // has been added yet, this adds the instance to the realm. [realm addOrUpdateObject:jones]; Person *bowie = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Bowie"}]; // Judging by the ID, it's the same person, just with a different name. // This overwrites the original entry (i.e. Jones -> Bowie). [realm addOrUpdateObject:bowie]; }];
You can also partially update an object by passing the primary key and a subset of the values to update:
To upsert an object, call Realm.add(_:update:)
with the second parameter, update policy, set to .modified
.
let realm = try! Realm() try! realm.write { let person1 = Person(value: ["id": 1234, "name": "Jones"]) // Add a new person to the realm. Since nobody with ID 1234 // has been added yet, this adds the instance to the realm. realm.add(person1, update: .modified) let person2 = Person(value: ["id": 1234, "name": "Bowie"]) // Judging by the ID, it's the same person, just with a // different name. When `update` is: // - .modified: update the fields that have changed. // - .all: replace all of the fields regardless of // whether they've changed. // - .error: throw an exception if a key with the same // primary key already exists. realm.add(person2, update: .modified) }
You can also partially update an object by passing the primary key and a subset of the values to update:
To upsert an object, call Realm.create()
with the update mode set to modified
. The operation either inserts a
new object with the given primary key or updates an existing object that
already has that primary key.
// The C++ SDK does not currently support this API.
var id = ObjectId.GenerateNewId(); var item1 = new Item { Id = id, Name = "Defibrillate the Master Oscillator", Assignee = "Aimee" }; // Add a new person to the realm. Since nobody with the existing Id // has been added yet, this person is added. await realm.WriteAsync(() => { realm.Add(item1, update: true); }); var item2 = new Item { Id = id, Name = "Fluxify the Turbo Encabulator", Assignee = "Aimee" }; // Based on the unique Id field, we have an existing person, // but with a different name. When `update` is true, you overwrite // the original entry. await realm.WriteAsync(() => { realm.Add(item2, update: true); }); // item1 now has a Name of "Fluxify the Turbo Encabulator" // and item2 was not added as a new Item in the collection.
final id = ObjectId(); // Add Anakin Skywalker to the realm with primary key `id` final anakin = Person( id, "Anakin Skywalker", ); realm.write(() { realm.add<Person>(anakin); }); // Overwrite the 'Anakin' Person object // with a new 'Darth Vader' object final darthVader = Person(id, 'Darth Vader'); realm.write(() { realm.add<Person>(darthVader, update: true); });
realm.executeTransaction(r -> { ObjectId id = new ObjectId(); TurtleEnthusiast drew = new TurtleEnthusiast(); drew.set_id(id); drew.setName("Drew"); drew.setAge(25); // Add a new turtle enthusiast to the realm. Since nobody with this id // has been added yet, this adds the instance to the realm. r.insertOrUpdate(drew); TurtleEnthusiast andy = new TurtleEnthusiast(); andy.set_id(id); andy.setName("Andy"); // Judging by the ID, it's the same turtle enthusiast, just with a different name. // As a result, you overwrite the original entry, renaming "Drew" to "Andy". // the flag passed ensures that we only write the updated name field to the db r.copyToRealmOrUpdate(andy, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET); });
realm.write(() => { // Add a new person to the realm. Since nobody with ID 1234 // has been added yet, this adds the instance to the realm. person = realm.create( "Person", { _id: 1234, name: "Joe", age: 40 }, "modified" ); // If an object exists, setting the third parameter (`updateMode`) to // "modified" only updates properties that have changed, resulting in // faster operations. person = realm.create( "Person", { _id: 1234, name: "Joseph", age: 40 }, "modified" ); });
realm.write { val existingFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first() assertEquals(existingFrog.name, "Kermit") // Use copyToRealm() to insert the object with the primary key // ** UpdatePolicy determines whether to update or throw an error if object already exists** copyToRealm(Frog().apply { _id = PRIMARY_KEY_VALUE name = "Wirt" age = 4 species = "Greyfrog" owner = "L'oric" }, UpdatePolicy.ALL) val upsertFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first() assertEquals(upsertFrog.name, "Wirt") }
realm.executeTransaction { r: Realm -> val id = ObjectId() val drew = TurtleEnthusiast() drew._id = id drew.name = "Drew" drew.age = 25 // Add a new turtle enthusiast to the realm. Since nobody with this id // has been added yet, this adds the instance to the realm. r.insertOrUpdate(drew) val andy = TurtleEnthusiast() andy._id = id andy.name = "Andy" // Judging by the ID, it's the same turtle enthusiast, just with a different name. // As a result, you overwrite the original entry, renaming "Drew" to "Andy". r.copyToRealmOrUpdate(andy, ImportFlag.CHECK_SAME_VALUES_BEFORE_SET) }
RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ // Only update the provided values. // Note that the "name" property will remain the same // for the person with primary key "_id" 123. [Person createOrUpdateModifiedInRealm:realm withValue:@{@"_id": @123, @"dogs": @[@[@"Buster", @5]]}]; }];
let realm = try! Realm() try! realm.write { // Use .modified to only update the provided values. // Note that the "name" property will remain the same // for the person with primary key "id" 123. realm.create(Person.self, value: ["id": 123, "dogs": [["Buster", 5]]], update: .modified) }
// The documentation does not currently have this code example in TypeScript. // Please refer to the other languages or related pages for example code.
Initialize Objects with a Value
Some of the SDKs provide specific methods to initialize objects with a value. Others use language-idiomatic methods to set the values of objects during initialization.
Some Property Types are Only Mutable in a Write Transaction
Some property types are only mutable in a write transaction. For example, you can instantiate an object with a Set property, but you can only set that property's value in a write transaction. You cannot initialize the object with a value for that property unless you do so inside a write transaction.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
You can initialize an object by passing an initializer value to RLMObject initWithValue. The initializer value can be a key-value coding compliant object, a dictionary, or an array containing one element for each managed property.
Note
When using an array as an initializer value, you must include all properties in the same order as they are defined in the model.
You can initialize an object by passing an initializer value to Object.init(value:). The initializer value can be a key-value coding compliant object, a dictionary, or an array containing one element for each managed property.
Note
When using an array as an initializer value, you must include all properties in the same order as they are defined in the model.
This SDK does not provide specialized methods to initialize objects with a value. Instead, use standard language features to create objects with initial values, or set the values after creating an object.
// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
// The Flutter SDK does not currently support this API.
// The Java SDK does not support this API.
// The Node.js SDK does not currently support this API.
// The Kotlin SDK does not currently support this API.
// The Java SDK does not support this API.
// (1) Create a Dog object from a dictionary Dog *myDog = [[Dog alloc] initWithValue:@{@"name" : @"Pluto", @"age" : @3}]; // (2) Create a Dog object from an array Dog *myOtherDog = [[Dog alloc] initWithValue:@[@"Pluto", @3]]; RLMRealm *realm = [RLMRealm defaultRealm]; // Add to the realm with transaction [realm transactionWithBlock:^() { [realm addObject:myDog]; [realm addObject:myOtherDog]; }];
You can even initialize related or embedded objects by nesting initializer values:
// Instead of using pre-existing dogs... Person *aPerson = [[Person alloc] initWithValue:@[@123, @"Jane", @[aDog, anotherDog]]]; // ...we can create them inline Person *anotherPerson = [[Person alloc] initWithValue:@[@123, @"Jane", @[@[@"Buster", @5], @[@"Buddy", @6]]]];
// (1) Create a Dog object from a dictionary let myDog = Dog(value: ["name": "Pluto", "age": 3]) // (2) Create a Dog object from an array let myOtherDog = Dog(value: ["Fido", 5]) let realm = try! Realm() // Add to the realm inside a transaction try! realm.write { realm.add([myDog, myOtherDog]) }
You can even initialize related or embedded objects by nesting initializer values:
// Instead of using pre-existing dogs... let aPerson = Person(value: [123, "Jane", [aDog, anotherDog]]) // ...we can create them inline let anotherPerson = Person(value: [123, "Jane", [["Buster", 5], ["Buddy", 6]]])
// This API is not currently available in TypeScript.
Create Objects from JSON
Working with JSON returned from an API is a common development use case. Most of the supported SDK languages do not directly support creating objects from JSON. However, you may use language or platform-idiomatic APIs to transform JSON to a structure that matches your object schema, and create a matching object. Or you may model unstructured data to work with unstructured data that is highly variable or whose structure is unknown at runtime.
This language is currently missing an example of how to create objects from JSON.
This language is currently missing an example of how to create objects from JSON.
This language is currently missing an example of how to create objects from JSON.
You can insert objects into the database from JSON. The SDK
supports creating objects from String
,
JSONObject, and
InputStream types.
The SDK ignores any properties present in the JSON that are
not defined in the SDK object schema.
The following example demonstrates how to create a single object from JSON with createObjectFromJson() or multiple objects from JSON with createAllFromJson():
This language is currently missing an example of how to create objects from JSON.
This language is currently missing an example of how to create objects from JSON.
You can insert objects into the database from JSON. The SDK
supports creating objects from String
,
JSONObject, and
InputStream types.
The SDK ignores any properties present in the JSON that are
not defined in the SDK object schema.
The following example demonstrates how to create a single object from JSON with createObjectFromJson() or multiple objects from JSON with createAllFromJson():
The SDK does not directly support JSON, but you can use NSJSONSerialization to convert JSON into a value that you can pass to RLMObject createInRealm(withValue:).
Nested objects or arrays in the JSON map to to-one or to-many relationships.
The JSON property names and types must match the destination object model exactly. For example:
float
properties must be initialized with float-backedNSNumbers
.Date
andData
properties cannot be inferred from strings. Convert them to the appropriate type before passing to RLMObject createInRealm(withValue:).Required properties cannot be
null
or missing in the JSON.
The SDK ignores any properties in the JSON not defined in the object schema.
Tip
If your JSON schema doesn't exactly align with your SDK objects, consider using a third-party framework to transform your JSON. There are many model mapping frameworks that work with the SDK. See a partial list in the realm-swift repository.
The SDK does not directly support JSON, but you can use JSONSerialization.jsonObject(with:options:) to convert JSON into a value that you can pass to Realm.create(_:value:update:).
Nested objects or arrays in the JSON map to to-one or to-many relationships.
The JSON property names and types must match the destination object model exactly. For example:
float
properties must be initialized with float-backedNSNumbers
.Date
andData
properties cannot be inferred from strings. Convert them to the appropriate type before passing to Realm.create(_:value:update:).Required properties cannot be
null
or missing in the JSON.
The SDK ignores any properties in the JSON not defined in the object schema.
Tip
If your JSON schema doesn't exactly align with your SDK objects, consider using a third-party framework to transform your JSON. There are many model mapping frameworks that work with the SDK. See a partial list in the realm-swift repository.
This language is currently missing an example of how to create objects from JSON.
// The documentation does not currently have this code example in C++. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in C#. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart. // Please refer to the other languages or related pages for example code.
// Insert from a string realm.executeTransaction(new Realm.Transaction() { public void execute(Realm realm) { realm.createObjectFromJson(Frog.class, "{ name: \"Doctor Cucumber\", age: 1, species: \"bullfrog\", owner: \"Wirt\" }"); } }); // Insert multiple items using an InputStream realm.executeTransaction(new Realm.Transaction() { public void execute(Realm realm) { try { InputStream inputStream = new FileInputStream( new File("path_to_file")); realm.createAllFromJson(Frog.class, inputStream); } catch (IOException e) { throw new RuntimeException(e); } } });
// The documentation does not currently have this code example in JavaScript. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Kotlin. // Please refer to the other languages or related pages for example code.
// Insert from a string realm.executeTransaction { realm -> realm.createObjectFromJson( Frog::class.java, "{ name: \"Doctor Cucumber\", age: 1, species: \"bullfrog\", owner: \"Wirt\" }" ) } // Insert multiple items using an InputStream realm.executeTransaction { realm -> try { val inputStream: InputStream = FileInputStream(File("path_to_file")) realm.createAllFromJson(Frog::class.java, inputStream) } catch (e: IOException) { throw RuntimeException(e) } }
// Specify a dog toy in JSON NSData *data = [@"{\"name\": \"Tennis ball\"}" dataUsingEncoding: NSUTF8StringEncoding]; RLMRealm *realm = [RLMRealm defaultRealm]; // Insert from NSData containing JSON [realm transactionWithBlock:^{ id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; [DogToy createInRealm:realm withValue:json]; }];
// Specify a dog toy in JSON let data = "{\"name\": \"Tennis ball\"}".data(using: .utf8)! let realm = try! Realm() // Insert from data containing JSON try! realm.write { let json = try! JSONSerialization.jsonObject(with: data, options: []) realm.create(DogToy.self, value: json) }
// The documentation does not currently have this code example in TypeScript. // Please refer to the other languages or related pages for example code.
Create an Unmanaged Copy of an Object
Some of the SDKs provide APIs to create an unmanaged, in-memory copy of a managed object or collection. In other SDKs, this API is not needed or not currently implemented.
Create an unmanaged version of a managed object by calling the detach()
function. This returns a value of the managed type. For example, calling
the detach()
function on a managed string property of a managed object
returns a std::string
copy of that property.
The SDK does not provide a C# API to directly create an unmanaged copy of an object. Instead, you can use a third-party library such as AutoMapper to create unmanaged objects.
The API to create an unmanaged copy of an object is either not needed or not currently supported in this SDK.
Use realm.copyFromRealm() to create an in-memory instance of a database object.
The API to create an unmanaged copy of an object is either not needed or not currently supported in this SDK.
Create an unmanaged copy of a managed object by passing it to
copyFromRealm().
For collections, this is a deep copy that includes all referenced objects up
to the specified depth
.
In the following example, we create an unmanaged copy of an existing
managed Pond
object that contains a list of two Frog
objects.
After copying the object from the database, we confirm that the copy is
unmanaged and contains both referenced Frog
objects:
Use realm.copyFromRealm() to create an in-memory instance of a database object.
The API to create an unmanaged copy of an object is either not needed or not currently supported in this SDK.
The API to create an unmanaged copy of an object is either not needed or not currently supported in this SDK.
The API to create an unmanaged copy of an object is either not needed or not currently supported in this SDK.
// The documentation does not currently have this code example in C++. // Please refer to the other languages or related pages for example code.
// The .NET SDK does not currently support this API.
// The Flutter SDK does not currently support this API.
// The documentation does not have this code example in Java. // Please refer to the other languages or related pages for example code.
// The Node.js SDK does not currently support this API.
realm.writeBlocking { // Fetch the managed object you want to copy val managedPond = query<Pond>("name == $0", "Big Pond").find().first() assertTrue(managedPond.isManaged()) // Create an unmanaged copy of the object val unmanagedPond = copyFromRealm(managedPond) assertFalse(unmanagedPond.isManaged()) Log.v("Unmanaged pond name: ${unmanagedPond.name}") // Confirm the unmanaged copy contains all elements // in the copied object's RealmList val unmanagedFrogs = unmanagedPond.frogsThatLiveHere assertFalse(unmanagedFrogs[0].isManaged()) assertFalse(unmanagedFrogs[1].isManaged()) assertEquals(2, unmanagedFrogs.size) Log.v("Unmanaged frogs: ${unmanagedFrogs[0].name}, ${unmanagedFrogs[1].name}") }
Unmanaged pond name: Big Pond Unmanaged frogs: Kermit, Froggy Jay
// The documentation does not have this code example in Kotlin for the Java SDK. // Please refer to the other languages or related pages for example code.
// The Swift SDK does not currently support this API.
// The Swift SDK does not currently support this API.
// This API is not currently available in TypeScript.
Copy an Object to Another Database
You can copy objects that are managed by one database instance to another database instance.
The selected language does not currently have an example of how to copy an object to another database instance.
The SDK does not provide a C# API to directly copy an object to another database instance. Instead, you can use a third-party library such as AutoMapper to create unmanaged objects and then copy them into another database instance.
The selected language does not currently have an example of how to copy an object to another database instance.
Use realm.copyToRealm() in a write transaction to copy a managed object to another database instance.
Alternately, to copy an object that does not exist, or update an object that does exist, use realm.copyToRealmOrUpdate(). This copies an object where the target database instance does not contain an object with the same primary key. If the target database instance already contains an object with a matching primary key, it updates the object.
To copy a managed object to another database instance, call the Realm.create() method in a write transaction with the object to copy. You can optionally specify the UpdateMode to determine how to handle copying objects where the target database instance already contains an object with a matching primary key.
You can copy an SDK object to a MutableRealm instance with the copyToRealm() method. The UpdatePolicy you specify determines how to handle copying objects where the target database instance already contains an object with a matching primary key.
Use realm.copyToRealm() in a write transaction to copy a managed object to another database instance.
Alternately, to copy an object that does not exist, or update an object that does exist, use realm.copyToRealmOrUpdate(). This copies an object where the target database instance does not contain an object with the same primary key. If the target database instance already contains an object with a matching primary key, it updates the object.
To copy a managed object to another database instance, call the RLMObject createOrUpdateInRealm:withValue or RLMObject createOrUpdateModifiedInRealm:withValue method in a write transaction.
If the object type does not have a primary key, or no object with a matching primary key exists, this method creates a new object in the target database instance.
If an object with a matching primary key already exists in the target
database instance, createOrUpdateInRealm
sets each property defined in its
schema by copying from value using key-value coding.
Alternately, createOrUpdateModifiedInRealm
only sets values which have
changed. Checking which properties have changed imposes a small amount of
overhead, and so this method may be slower when all or nearly all of the
properties being set have changed. If most or all of the properties being set
have not changed, this method is much faster than unconditionally setting
all of them. It also reduces how much data has to be written to the database,
saving both i/o time and disk space.
To copy a managed object to another database instance, call the create(value: update:) method in a write transaction.
If the object type does not have a primary key, or no object with a matching
primary key exists, this method creates a new object in the target database
instance. If an object with a matching primary key already exists in the target
database instance, and you set the update policy to .modified
or .all
, this method
updates the existing object returns a reference to it.
To copy a managed object to another database instance, call the Realm.create() method in a write transaction with the object to copy. You can optionally specify the UpdateMode to determine how to handle copying objects where the target database instance already contains an object with a matching primary key.
// The documentation does not currently have this code example in C++. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in C#. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart. // Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Java. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in JavaScript. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Kotlin. // Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Objective-C. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Swift. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in TypeScript. // Please refer to the other languages or related pages for example code.
Create Objects in the Background
When performing large write operations, you may want to create objects in the background. This avoids blocking the UI thread while performing large write operations. This is particularly useful when using Device Sync, where you don't know when and for how long the Sync client will be writing.
Open a write transaction with the or Realm.WriteAsync() method to avoid blocking the UI thread.
You can add, modify, or delete objects asynchronously using Realm.writeAsync().
When you use Realm.writeAsync()
to perform write operations, waiting
to obtain the write lock and committing a transaction occur in the background.
Only the write itself occurs on the main process.
Use the Background Write API
You can add, modify, or delete objects in the background using writeAsync.
With writeAsync
, you don't need to pass a thread-safe reference or frozen objects
across threads. Instead, call realm.writeAsync
. You can provide
a completion block for the method to execute on the source thread after
the write completes or fails.
Things to consider when performing background writes:
Async writes block closing or invalidating the database
You can explicitly commit or cancel transactions
Wait for Async Writes to Complete
The SDK provides a Bool
to signal whether the database is currently
performing an async write. The
isPerformingAsynchronousWriteOperations
variable becomes true
after a call to one of:
writeAsync
beginAsyncWrite
commitAsyncWrite
It remains true until all scheduled async write operations have completed. While this is true, this blocks closing or invalidating the database.
Commit or Cancel an Async Write
To complete an async write, you or the SDK must call either:
When you use the writeAsync
method, the SDK handles committing or
canceling the transaction. This provides the convenience of the async write
without the need to manually keep state tied to the scope of the object.
However, while in the writeAsync
block, you can explicitly call
commitAsyncWrite
or cancelAsyncWrite
. If you return without
calling one of these methods, writeAsync
either:
Commits the write after executing the instructions in the write block
Returns an error
In either case, this completes the writeAsync
operation.
For more control over when to commit or cancel the async write transaction,
use the beginAsyncWrite
method. When you use this method, you must
explicitly commit the transactions. Returning without committing an async
write cancels the transaction. beginAsyncWrite
returns an ID that you
can pass to cancelAsyncWrite
.
commitAsyncWrite
asynchronously commits a write transaction. This is
the step that persists the data to the database. commitAsyncWrite
can
take an onComplete
block. This block executes on the source thread
once the commit completes or fails with an error.
Calling commitAsyncWrite
immediately returns. This allows the caller
to proceed while the SDK performs the I/O on a background thread. This method
returns an ID that you can pass to cancelAsyncWrite
. This cancels the
pending invocation of the completion block. It does not cancel the commit
itself.
You can group sequential calls to commitAsyncWrite
. Batching these calls
improves write performance; particularly when the batched transactions are
small. To permit grouping transactions, set the isGroupingAllowed
parameter to true
.
You can call cancelAsyncWrite
on either beginAsyncWrite
or
commitAsyncWrite
. When you call it on beginAsyncWrite
, this cancels
the entire write transaction. When you call it on commitAsyncWrite
, this
cancels only an onComplete
block you may have passed to
commitAsyncWrite
. It does not cancel the commit itself. You need the ID
of the beginAsyncWrite
or the commitAsyncWrite
you want to cancel.
Use Swift Concurrency Features
Write to an Actor-Isolated Realm
You can use Swift concurrency features to write asynchronously to an actor-isolated database.
The following function is taken from the example RealmActor
defined on the
Define a Custom Database Actor page. It shows how you might
write to an actor-isolated database:
func createTodo(name: String, owner: String, status: String) async throws { try await realm.asyncWrite { realm.create(Todo.self, value: [ "_id": ObjectId.generate(), "name": name, "owner": owner, "status": status ]) } }
And you might perform this write using Swift's async syntax:
func createObject() async throws { // Because this function is not isolated to this actor, // you must await operations completed on the actor try await actor.createTodo(name: "Take the ring to Mount Doom", owner: "Frodo", status: "In Progress") let taskCount = await actor.count print("The actor currently has \(taskCount) tasks") } let actor = try await RealmActor() try await createObject()
This operation does not block or perform I/O on the calling thread. For more information about writing to a database using Swift concurrency features, refer to Use Atlas Device SDK for Swift with Actors.
Perform Writes using Async/Await Syntax
The asyncWrite() API allows for performing async writes using Swift async/await syntax.
The asyncWrite()
API suspends the calling task while waiting for its
turn to write rather than blocking the thread. In addition, the actual
I/O to write data to disk is done by a background worker thread. For small
writes, using this function on the main thread may block the main thread
for less time than manually dispatching the write to a background thread.
// The documentation does not currently have this code example in C++. // Please refer to the other languages or related pages for example code.
var testItem = new Item { Name = "Do this thing", Status = ItemStatus.Open.ToString(), Assignee = "Aimee" }; await realm.WriteAsync(() => { realm.Add(testItem); }); // Or var testItem2 = await realm.WriteAsync(() => { return realm.Add<Item>(new Item { Name = "Do this thing, too", Status = ItemStatus.InProgress.ToString(), Assignee = "Satya" }); } );
// Add Leia to the realm using `writeAsync` Person leia = Person(ObjectId(), "Leia"); realm.writeAsync(() { realm.add<Person>(leia); });
// The documentation does not have this code example in Java. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in JavaScript. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Kotlin. // Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK. // Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Objective-C. // Please refer to the other languages or related pages for example code.
let realm = try! Realm() // Query for a specific person object on the main thread let people = realm.objects(Person.self) let thisPerson = people.where { $0.name == "Dachary" }.first // Perform an async write to add dogs to that person's dog list. // No need to pass a thread-safe reference or frozen object. realm.writeAsync { thisPerson?.dogs.append(objectsIn: [ Dog(value: ["name": "Ben", "age": 13]), Dog(value: ["name": "Lita", "age": 9]), Dog(value: ["name": "Maui", "age": 1]) ]) } onComplete: { _ in // Confirm the three dogs were successfully added to the person's dogs list XCTAssertEqual(thisPerson!.dogs.count, 3) // Query for one of the dogs we added and see that it is present let dogs = realm.objects(Dog.self) let benDogs = dogs.where { $0.name == "Ben" } XCTAssertEqual(benDogs.count, 1) }
// The documentation does not currently have this code example in TypeScript. // Please refer to the other languages or related pages for example code.