Docs Menu

Docs HomeDevelop ApplicationsAtlas Device SDKs

Object Models - C++ SDK

On this page

  • Object Types and Schemas
  • Database Schema
  • Object Model
  • Object Schema
  • Define a New Object Type
  • Specify a Primary Key
  • Ignore a Property
  • Define an Embedded Object
  • Define an Asymmetric Object

Atlas Device SDK applications model data as objects composed of field-value pairs that each contain one or more supported data types.

Every database 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 database schema is a list of valid object schemas that the database may contain. Every database object must conform to an object type that's included in its database's schema.

When opening a database, you must specify which models are available by passing the models to the template you use to open the database. Those models must have schemas, and this list of schemas becomes the database schema.

If the database already contains data when you open it, the SDK 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 the database, refer to Configure & Open a Realm - C++ SDK

Your object model is the core structure that gives the database information about how to interpret and store the objects in your app. The C++ SDK object model is a regular C++ class or a struct that contains a collection of properties. The properties that you want to persist must use supported data types. Properties are also the mechanism for establishing relationships between object types.

When you define your C++ class or struct, you must also provide an object schema. The schema is a C++ macro that gives the SDK information about which properties to persist, and what type of database object it is.

You must define your SDK object model within the realm namespace.

A C++ SDK object schema maps properties for a specific object type. The SDK schemas are macros that give the SDK the information it needs to store and retrieve the objects. A schema must accompany every object model you want to persist, and it may be one of:

  • REALM_SCHEMA

  • REALM_EMBEDDED_SCHEMA

  • REALM_ASYMMETRIC_SCHEMA

You must define the schema and your object model within the realm namespace.

In the C++ SDK, you can define your models as regular C++ structs or classes. Provide an Object Schema with the object type name and the names of any properties that you want to persist to the database. When you add the object to the database, the SDK ignores any properties that you omit from the schema.

You must declare your object and the schema within the realm namespace. You must then use the realm namespace when you initialize and perform CRUD operations with the object.

namespace realm {
struct Dog {
std::string name;
int64_t age;
};
REALM_SCHEMA(Dog, name, age)
struct Person {
realm::primary_key<int64_t> _id;
std::string name;
int64_t age;
// Create relationships by pointing an Object field to another struct or class
Dog *dog;
};
REALM_SCHEMA(Person, _id, name, age, dog)
} // namespace realm

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 the database. The C++ SDK 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 C++ SDK supports primary keys of the following types, and their optional variants:

  • int64_t

  • realm::object_id

  • realm::uuid

  • std::string

Additionally, a required realm::enum property can be a primary key, but realm::enum cannot be optional if it is used as a primary key.

Set a property as a primary key with the primary_key template:

struct Person {
realm::primary_key<int64_t> _id;
std::string name;
int64_t age;
// Create relationships by pointing an Object field to another struct or class
Dog *dog;
};
REALM_SCHEMA(Person, _id, name, age, dog)

Your model may include properties that the database does not store.

The database ignores any properties not included in the Object Schema.

namespace realm {
struct Employee {
realm::primary_key<int64_t> _id;
std::string firstName;
std::string lastName;
// You can use this property as you would any other member
// Omitting it from the schema means the SDK ignores it
std::string jobTitle_notPersisted;
};
// The REALM_SCHEMA omits the `jobTitle_notPersisted` property
// The SDK does not store and cannot retrieve a value for this property
REALM_SCHEMA(Employee, _id, firstName, lastName)
} // namespace realm

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.

The C++ SDK 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 database object. The SDK 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.

Provide a REALM_EMBEDDED_SCHEMA with the struct or class name and the names of any properties that you want the database to persist.

Define a property as an embedded object on the parent object by setting a pointer to the embedded object's type.

namespace realm {
struct 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
std::string emailAddress;
std::string phoneNumber;
};
REALM_EMBEDDED_SCHEMA(ContactDetails, emailAddress, phoneNumber)
struct Business {
realm::object_id _id;
std::string name;
ContactDetails *contactDetails;
};
REALM_SCHEMA(Business, _id, name, contactDetails)
} // namespace realm

You can use Data Ingest to sync an object unidirectionally from your device to the database linked to your Atlas App Services App.

An asymmetric_object broadly has the same supported types as realm::object, with a few exceptions:

  • Asymmetric objects can link to the following types: - object - embedded_object - std::vector<embedded_object>

Asymmetric objects do not function in the same way as other database objects. You cannot:

  • Remove an asymmetric object from the device database

  • Query an asymmetric object from the device database

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.

In the C++ SDK, define an asymmetric object the same way you would a regular C++ struct or class. Provide a REALM_ASYMMETRIC_SCHEMA with the struct or class name and the names of any properties that you want the database to persist.

struct WeatherSensorReading {
realm::primary_key<realm::object_id> _id{realm::object_id::generate()};
std::string deviceId;
double temperatureInFahrenheit;
int64_t windSpeedInMph;
};
REALM_ASYMMETRIC_SCHEMA(WeatherSensorReading, _id, deviceId,
temperatureInFahrenheit, windSpeedInMph)
← Model Data - C++ SDK