Manage Sync Subscriptions - C++ SDK
On this page
- Prerequisites
- Align Subscriptions with Backend App
- Manage Your Subscriptions
- Verify Number of Subscriptions or Find a Specific Subscription
- Add Sync Subscriptions
- Subscribe to All Objects of a Type
- Subscribe to Objects that Match a Query
- Update Sync Subscriptions
- Remove Sync Subscriptions
- Remove a Specific Subscription
- Remove All Subscriptions
- Refresh the Realm After Updating Subscriptions
Flexible Sync uses subscriptions and permissions to determine which data to sync between your Atlas App Services App and your client device. In the client, query subscriptions manage and filter the object types that can sync to the realm.
Prerequisites
To use Flexible Sync in your app, you must:
The setup code for the examples on this page handles these prerequisites:
// Initialize the App, authenticate a user, and open the database auto appConfig = realm::App::configuration(); appConfig.app_id = APP_ID; auto app = realm::App(appConfig); auto user = app.login(realm::App::credentials::anonymous()).get(); auto syncConfig = user.flexible_sync_configuration(); auto syncedRealm = realm::db(syncConfig);
Additionally, models used with Sync must contain a primary key property
named _id
. For more information on defining a model with a primary key,
refer to Specify a Primary Key.
Align Subscriptions with Backend App
Your client-side subscription queries must align with the Device Sync configuration in your backend App Services App.
You subscription queries can either:
Query all objects of a type.
Query object of a type that match backend App's queryable fields.
To learn more about configuring queryable fields, refer to Queryable Fields in the App Services documentation.
A synced realm must have one or more subscriptions in order to be able to read and write data to the realm. You can only write data to the realm that matches one or more subscriptions, and matches the user's permissions. If you attempt to write objects to a realm that do not match a subscription, or for which the user does not have permission to perform the write, you get a compensating write from the server and the write reverts.
Manage Your Subscriptions
When configuring Flexible Sync on the backend, you specify which fields your client application can query. In the client application, the sync_subscription_set is a list of zero or more sync_subscription objects that determine what objects the realm can store.
The Realm C++ SDK also has a mutable_sync_subscription_set that enables you to
add, change, and remove sync_subscription
objects.
Warning
Query Size Limit
The size limit for any given query subscription in your subscription set is 256 kB. Exceeding this limit results in a LimitsExceeded Error.
Verify Number of Subscriptions or Find a Specific Subscription
When your app first opens a synced realm, you may want to verify that it has the expected number of subscriptions or has a specific subscription.
You can get this information by accessing the subscriptions()
public
member function of a realm. This
provides the sync_subscription_set where you can use the
size()
or find()
member functions.
// Check the subscription count CHECK(syncedRealm.subscriptions().size() == 1); // Find a specific subscription by name auto puppySubscription = *syncedRealm.subscriptions().find("puppies"); CHECK(puppySubscription.name == "puppies"); // Get information about the subscription CHECK(puppySubscription.object_class_name == "Dog"); CHECK(puppySubscription.query_string == "age < 3");
Add Sync Subscriptions
To update a subscription set, use the subscription().updates()
function.
This gives you access to a mutable_sync_subscription_set where you can use the
use the add()
function to add a new Sync subscription.
This template requires the object type of the object you want to sync, and a string name for the subscription.
Subscribe to All Objects of a Type
You can subscribe to all objects of a type. This enables the synced realm to read and write any objects of the type where the user's permissions match the server-side permissions.
auto updateSubscriptionSuccess = syncedRealm.subscriptions() .update([](realm::mutable_sync_subscription_set &subs) { subs.add<realm::Dog>("dogs"); }) .get(); // The .update() function returns a bool, which confirms whether or not the // update succeeded REQUIRE(updateSubscriptionSuccess == true); // You can check the .size() of the subscription set, which tells you the // number of sync_subscription objects in the set CHECK(syncedRealm.subscriptions().size() == 1);
Subscribe to Objects that Match a Query
If you only want to subscribe to a subset of objects, provide a query to filter the subscription.
updateSubscriptionSuccess = syncedRealm.subscriptions() .update([](realm::mutable_sync_subscription_set &subs) { subs.add<realm::Dog>( "puppies", [](auto &obj) { return obj.age < 3; }); }) .get(); REQUIRE(updateSubscriptionSuccess == true); CHECK(syncedRealm.subscriptions().size() == 1);
When you filter a subscription, you cannot write objects that do not match
the filter. In this example, the query matches Dog
objects whose age
is
less than 3
. The realm does not sync any dogs who are 3 or older. This
filter also applies to writes. If you try to write a Dog
object where
the age
is 4
, you get a compensating write error and the write
reverts.
Note
The C++ SDK does not yet support the full range of query expressions that the other SDKs provide.
Update Sync Subscriptions
To update a subscription set, use the subscription().updates()
function.
This gives you access to a mutable_sync_subscription_set where you can use the
update_subscription()
function to update a specific sync_subscription.
You can change a sync_subscription
's query in an update. You can add, remove,
or update the query string for a given sync_subscription
.
updateSubscriptionSuccess = syncedRealm.subscriptions() .update([](realm::mutable_sync_subscription_set &subs) { subs.update_subscription<realm::Dog>( "puppies", [](auto &obj) { return obj.age < 2; }); }) .get(); REQUIRE(updateSubscriptionSuccess == true);
Remove Sync Subscriptions
To update a subscription set, use the subscription().updates()
function.
This gives you access to a mutable_sync_subscription_set where you can use the
remove()
or clear()
functions to remove subscriptions.
Remove a Specific Subscription
You can remove a specific subscription by name using the remove()
function.
Removing a subscription by name throws an error if the subscription does
not exist, so you should check for a subscription before removing it.
auto removeSubscriptionSuccess = syncedRealm.subscriptions() .update([](realm::mutable_sync_subscription_set &subs) { subs.remove("dogs"); }) .get(); REQUIRE(removeSubscriptionSuccess == true);
Remove All Subscriptions
You can remove all subscriptions in a subscription set using the clear()
function.
// You can use .clear() inside a mutable_sync_subscription_set to clear all // sync_subscription objects from the set auto updateSubscriptionSuccess = syncedRealm.subscriptions() .update( [](realm::mutable_sync_subscription_set &subs) { subs.clear(); }) .get(); CHECK(updateSubscriptionSuccess == true); CHECK(syncedRealm.subscriptions().size() == 0);
Refresh the Realm After Updating Subscriptions
After you update subscriptions, call refresh()
on the realm. This updates the realm and outstanding objects
managed by the realm to point to the most recent data.
syncedRealm.refresh();