Docs Menu

Docs HomeRealm

Object Models - C++ SDK (Alpha)

On this page

  • Key Concept: Object Types & Schemas
  • Realm Schema
  • Realm Object Model
  • Realm Object Schema
  • Define a New Object Type
  • Specify a Primary Key
  • Ignore a Property
  • Define an Embedded Object
  • Define an Asymmetric Object

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.

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)

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.

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.

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.

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"));

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"));
};

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"));
};

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 and std::vector<object> properties are not supported

    • embedded_object and std::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.

←  Model Data - C++ SDKSupported Types - C++ SDK (Alpha) →
Share Feedback
© 2023 MongoDB, Inc.

About

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