Object Models - C++ SDK (Alpha)
On this page
Key Concept: Object Types & Schemas
Realm Database applications model data as objects composed of field-value pairs that each contain one or more supported data types.
Every Realm object has an object type that refers to the object's class. Objects of the same type share an object schema that defines the properties and relationships of those objects.
Realm Schema
A realm schema is a list of valid object schemas that a realm may contain. Every Realm object must conform to an object type that's included in its realm's schema.
When opening a realm, you must specify which models are available by passing the models to the template you use to open the realm. Those models must have schemas, and this list of schemas becomes the realm schema.
If a realm already contains data when you open it, Realm Database validates each object to ensure that an object schema was provided for its type and that it meets all of the constraints specified in the schema.
For more information about how to open a realm, refer to: Configure & Open a Realm - C++ SDK (Alpha)
Realm Object Model
Your Realm object model is the core structure that gives Realm information about how to interpret and store the objects in your app. The C++ Realm object model is a class or a struct that subclasses one of the Realm object types. The object model contains a collection of properties. You annotate the properties in the model to give Realm information about each property:
The data type and whether the property is optional or required
Whether Realm should store or ignore the property
Properties are also the mechanism for establishing relationships between Realm object types.
You use this object model like any other C++ class or struct when you initialize your objects.
In addition to property information, each C++ Realm object model must expose a schema.
Realm Object Schema
A C++ realm object schema maps property names, relationships, and any property metadata for a specific object type. Because C++ does not have reflection, your model must expose a public static constexpr member that explicitly declares your schema. The object schema includes details like the property name and type, whether the property is a primary key, and whether it forms a relationship with other object types.
Define a New Object Type
You can define your models as classes or structs that inherit from realm::object. The Realm C++ SDK uses CRTP to simplify working with Realm objects. With this implementation, you pass the object's type as a template paramater when you declare your object struct.
You must declare any property you want to store (persist) in a realm as
realm::persisted. Your model
must also expose a public static constant expression (constexpr
) member
called schema
. Use the realm::schema and realm::property templates to describe your schema.
Realm ignores any members not declared as realm::persisted
and not
declared in the schema.
struct Dog : realm::object<Dog> { realm::persisted<std::string> name; realm::persisted<int64_t> age; static constexpr auto schema = realm::schema("Dog", realm::property<&Dog::name>("name"), realm::property<&Dog::age>("age")); }; struct Person : realm::object<Person> { realm::persisted<std::string> _id; realm::persisted<std::string> name; realm::persisted<int64_t> age; // Create relationships by pointing an Object field to another Class realm::persisted<std::optional<Dog>> dog; static constexpr auto schema = realm::schema("Person", realm::property<&Person::_id, true>("_id"), // primary key realm::property<&Person::name>("name"), realm::property<&Person::age>("age"), realm::property<&Person::dog>("dog")); };
Note
Class names are limited to a maximum of 57 UTF-8 characters.
Specify a Primary Key
You can designate a property as the primary key of your object.
Primary keys allow you to efficiently find, update, and upsert objects.
Primary keys are subject to the following limitations:
You can define only one primary key per object model.
Primary key values must be unique across all instances of an object in a realm. Realm Database throws an error if you try to insert a duplicate primary key value.
Primary key values are immutable. To change the primary key value of an object, you must delete the original object and insert a new object with a different primary key value.
Embedded objects cannot define a primary key.
If you are using Device Sync, your models must
have a primary key named _id
.
The Realm C++ SDK supports primary keys of the following types, required or optional:
realm::object_id
realm::uuid
realm::enum
std::string
You set a property as a primary key by passing true
to the second template parameter of the persisted
template:
static constexpr auto schema = realm::schema("Person", realm::property<&Person::_id, true>("_id"), // primary key realm::property<&Person::name>("name"), realm::property<&Person::age>("age"), realm::property<&Person::dog>("dog"));
Ignore a Property
Your model may include properties that Realm Database does not store. Realm
ignores any members not declared as realm::persisted
and not declared
in the schema.
struct Employee : realm::object<Employee> { realm::persisted<int64_t> _id; realm::persisted<std::string> firstName; realm::persisted<std::string> lastName; // Omitting the `realm::persisted` annotation means // realm ignores this property std::string jobTitle_notPersisted; // Your schema consists of properties that you want realm to store. // Omit properties that you want to ignore from the schema. static constexpr auto schema = realm::schema("Employee", realm::property<&Employee::_id, true>("_id"), realm::property<&Employee::firstName>("firstName"), realm::property<&Employee::lastName>("lastName")); };
Define an Embedded Object
An embedded object is a special type of object that models complex data about a specific object. Embedded objects are similar to relationships, but they provide additional constraints and map more naturally to the denormalized MongoDB document model.
Realm enforces unique ownership constraints that treat each embedded object as nested data inside of a single, specific parent object. An embedded object inherits the lifecycle of its parent object and cannot exist as an independent Realm object. Realm automatically deletes embedded objects if their parent object is deleted or when overwritten by a new embedded object instance.
You can declare an object as an embedded object that does not have a lifecycle independent of the object in which it is embedded. This differs from a to-one or to-many relationship, in which the related objects have independent lifecycles.
To declare an object as an embedded object, inherit from realm::embedded_object.
// Inherit from realm::embedded_object to declare an embedded object struct ContactDetails : realm::embedded_object<ContactDetails> { // Because ContactDetails is an embedded object, it cannot have its own _id // It does not have a lifecycle outside of the top-level object realm::persisted<std::string> emailAddress; realm::persisted<std::string> phoneNumber; static constexpr auto schema = realm::schema("ContactDetails", realm::property<&ContactDetails::emailAddress>("emailAddress"), realm::property<&ContactDetails::phoneNumber>("phoneNumber")); }; struct Business : realm::object<Business> { realm::persisted<int64_t> _id; realm::persisted<std::string> name; realm::persisted<std::optional<ContactDetails>> contactDetails; static constexpr auto schema = realm::schema("Business", realm::property<&Business::_id, true>("_id"), realm::property<&Business::name>("name"), realm::property<&Business::contactDetails>("contactDetails")); };
Define an Asymmetric Object
You can use Asymmetric Sync to sync an object unidirectionally from your device to the database linked to your Atlas App Services App. Define an asymmetric object by inheriting from realm::asymmetric_object.
struct WeatherSensorReading : realm::asymmetric_object<WeatherSensorReading> { realm::persisted<realm::object_id> _id{realm::object_id::generate()}; realm::persisted<std::string> deviceId; realm::persisted<double> temperatureInFahrenheit; realm::persisted<int64_t> windSpeedInMph; static constexpr auto schema = realm::schema("WeatherSensorReading", realm::property<&WeatherSensorReading::_id, true>("_id"), realm::property<&WeatherSensorReading::deviceId>("deviceId"), realm::property<&WeatherSensorReading::temperatureInFahrenheit>("temperatureInFahrenheit"), realm::property<&WeatherSensorReading::windSpeedInMph>("windSpeedInMph")); };
An asymmetric_object
broadly has the same supported types as realm::object
, with a few exceptions:
- Asymmetric objects can only link to embedded objects
object
andstd::vector<object>
properties are not supportedembedded_object
andstd::vector<embedded_object>
are supported
You cannot link to an asymmetric_object
from within an object
. Doing so
throws an error.
Asymmetric objects do not function in the same way as other Realm objects. You cannot:
Remove an asymmetric object from a realm
Query an asymmetric object
You can only create an asymmetric object, which then syncs unidirectionally to the Atlas database linked to your App with Device Sync.
For more information, see: Create an Asymmetric Object.