Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Sync Data

Manage Flexible Sync Subscriptions - Java SDK

Flexible Sync utiliza suscripciones y permisos para determinar qué datos sincronizar con tu aplicación.

Para usar Flexible Sync en el SDK:

  • Configure Flexible Sync on the backend

  • Initialize the app

  • Authenticate a user in your client project.

  • Abra el reino sincronizado con una configuración de sincronización flexible

  • Agrega suscripciones a la aplicación cliente

You can add, update, and remove query subscriptions to determine which data syncs to the client device.

Tip

This page details how to manage subscriptions for Flexible Sync.

Para obtener información general sobre el uso de Atlas Device Sync con el SDK, como sincronizar cambios en segundo plano o pausar una sesión de sincronización, consulta Sincronizar cambios entre dispositivos.

For information about setting up permissions for Flexible Sync, check out Flexible Sync Rules & Permissions.

Al configurar la sincronización flexible en el backend, se especifican los campos que la aplicación cliente puede consultar. En la aplicación cliente, utilice el subscriptions API para gestionar un conjunto de suscripciones a consultas específicas en campos consultables. Puede crear consultas con la interfaz fluida del SDK de Java o con el lenguaje de consulta Realm.

Importante

Flexible Sync no es compatible con todos los operadores disponibles en Realm Query Language. Consulta Limitaciones de RQL en Flexible Sync para obtener detalles.

Puede:

  • Add subscriptions

  • React to subscription state

  • Actualiza las suscripciones con nuevas queries

  • Remover suscripciones individuales o todas las suscripciones de un tipo de objeto Realm.

Data matching the subscription, where the user has the appropriate permissions, syncs between clients and the backend application.

You can specify an optional string name for your subscription.

Tip

Always Specify a Subscription Name

Especifique siempre un nombre de suscripción si su aplicación utiliza varias. Esto facilita la búsqueda, actualización y eliminación de suscripciones en otras partes de la aplicación.

When you create a subscription, Realm looks for data matching a query on a specific object type. You can have multiple subscription sets on different object types. You can also have multiple queries on the same object type.

You can create a subscription with an explicit name. Then, you can search for that subscription by name to update or remove it.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
// add a subscription with a name
subscriptions.add(Subscription.create("frogSubscription",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
// later, you can look up this subscription by name
Subscription subscription = realm.getSubscriptions().find("frogSubscription");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
// add a subscription with a name
subscriptions.add(
Subscription.create(
"frogSubscription",
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
// later, you can look up this subscription by name
val subscription =
realm.subscriptions.find("frogSubscription")
}
})

You can also search subscriptions by query. If you omit the name when creating a subscription, this is the only way to look up your subscription.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
// add a subscription without assigning a name
subscriptions.add(Subscription.create(
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
// later, you can look up this subscription by query
Subscription subscription = realm.getSubscriptions().find(realm.where(Frog.class)
.equalTo("species", "spring peeper"));
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
// add a subscription without assigning a name
subscriptions.add(
Subscription.create(
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
// later, you can look up this subscription by query
val subscription =
realm.subscriptions.find(
realm.where(
Frog::class.java
).equalTo("species", "spring peeper")
)
}
})

Nota

Suscripciones duplicadas

Subscription names must be unique. Adding a subscription with the same name as an existing subscription throws an error.

If you do not explicitly name a subscription, and instead subscribe to the same unnamed query more than once, Realm does not persist duplicate queries to the subscription set.

Si te suscribes a la misma query más de una vez con diferentes nombres, Realm mantiene ambas suscripciones en el conjunto de suscripción.

Add a subscription in a subscriptions write block. You append each new subscription to the client's Realm subscriptions.

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("subscriptionName",
realm.where(Frog.class)
.equalTo("species", "spring peeper")));
}
})
.build();
// instantiate a realm instance with the flexible sync configuration
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"subscriptionName",
realm.where(Frog::class.java)
.equalTo("species", "spring peeper")
)
)
}
.build()
// instantiate a realm instance with the flexible sync configuration
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})

Nota

Object Links

You must add both an object and its linked object to the subscription set to see a linked object.

Si los resultados de tu suscripción contienen un objeto con una propiedad que enlaza a un objeto no contenido en los resultados, el enlace parecerá ser nulo. No hay forma de distinguir si el valor de esa propiedad es legítimamente nulo, o si el objeto al que se enlaza existe pero está fuera del alcance de la suscripción de la consulta.

Writing an update to the subscription set locally is only one component of changing a subscription. After the local subscription change, the client synchronizes with the server to resolve any updates to the data due to the subscription change. This could mean adding or removing data from the synced realm. Use the waitForInitialRemoteData() builder method to force your application to block until client subscription data synchronizes to the backend before opening the realm:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("my subscription",
realm.where(Frog.class)
.equalTo("species", "poison dart")));
}
})
.waitForInitialRemoteData(2112, TimeUnit.MILLISECONDS)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"my subscription",
realm.where(Frog::class.java)
.equalTo("species", "poison dart")
)
)
}
.waitForInitialRemoteData(
2112,
TimeUnit.MILLISECONDS
)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})

También puede usar SubscriptionSet.waitForSynchronization() o SubscriptionSet.waitForSynchronizationAsync() para retrasar la ejecución hasta que se complete la sincronización de suscripción tras instanciar una conexión de sincronización.

Additionally, you can watch the state of the subscription set with the SubscriptionSet.State enum. You can use subscription state to:

  • Show a progress indicator while data is downloading

  • Find out when a subscription set becomes superseded

You can access the state of your application's subscription set using SubscriptionSet.getState().

Nota

Estado de suscripción 'Completo'

The subscription set state "complete" does not mean "sync is done" or "all documents have been synced". "Complete" means the following two things have happened:

  • The subscription has become the active subscription set that is currently being synchronized with the server.

  • The documents that matched the subscription at the time the subscription was sent to the server are now on the local device. Note that this does not necessarily include all documents that currently match the subscription.

El SDK de Realm no proporciona una manera de verificar si todos los documentos que coinciden con una suscripción se han sincronizado con el dispositivo.

SUPERSEDED is a SubscriptionSet.State that can occur when another thread writes a subscription on a different instance of the subscription set. If the state becomes SUPERSEDED, you must obtain a new instance of the subscription set before you can write to it.

Puedes actualizar las suscripciones con SubscriptionSet.update(). En este ejemplo, usamos MutableSubscriptionSet.addOrUpdate() para actualizar la consulta de la suscripción llamada "my frog subscription":

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create("my frog subscription",
realm.where(Frog.class)
.equalTo("name",
"Benedict Cumberburger")));
}
});
realm.subscriptions.update { subscriptions ->
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create(
"my frog subscription",
realm.where(Frog::class.java)
.equalTo(
"name",
"Benedict Cumberburger"
)
)
)
}

You cannot update subscriptions created without a name. However, you can look up unnamed subscriptions by their query, remove them from the subscription set, then add a new subscription with an updated query:

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
Subscription mySubscription = subscriptions.find(realm.where(Frog.class)
.equalTo("species",
"cane toad"));
subscriptions.remove(mySubscription);
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog.class)
.equalTo("species",
"albino cane toad")));
}
});
realm.subscriptions.update { subscriptions ->
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
val mySubscription =
subscriptions.find(
realm.where(
Frog::class.java
).equalTo(
"species",
"cane toad"
)
)
subscriptions.remove(mySubscription)
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog::class.java)
.equalTo(
"species",
"albino cane toad"
)
)
)
}

To remove subscriptions, you can:

  • Remove a single subscription query

  • Remove all subscriptions to a specific object type

  • Remove all subscriptions

Cuando elimina una consulta de suscripción, Realm elimina de forma asincrónica los datos sincronizados que coinciden con la consulta del dispositivo cliente.

Puedes eliminar una consulta de suscripción específica usando MutableSubscriptionSet.remove(). Puedes buscar la suscripción por nombre y luego pasar la suscripción devuelta a remove(), o pasar el nombre de la suscripción directamente a remove():

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
Subscription mySubscription = subscriptions.find("mySubscription");
subscriptions.remove(mySubscription);
}
});
realm.subscriptions.update { subscriptions ->
val mySubscription =
subscriptions.find("mySubscription")
subscriptions.remove(mySubscription)
}

Si desea eliminar todas las suscripciones a un tipo de objeto Realm específico, pase una clase al método removeAll():

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll(Frog.class);
}
});
realm.subscriptions.update { subscriptions ->
subscriptions.removeAll(
Frog::class.java
)
}

To remove all subscriptions from the subscription set, use removeAll() with no arguments:

Advertencia

Si elimina todas las suscripciones y no agrega una nueva, obtendrá un error. Un realm abierto con una configuración de sincronización flexible necesita al menos una suscripción para sincronizar con el servidor.

realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll();
}
});
realm.subscriptions.update { subscriptions -> subscriptions.removeAll() }

Adding an indexed queryable field to your App can improve performance for simple queries on data that is strongly partitioned. For example, an app where queries strongly map data to a device, store, or user, such as user_id == $0, “641374b03725038381d2e1fb”, is a good candidate for an indexed queryable field. However, an indexed queryable field has specific requirements for use in a query subscription:

  • The indexed queryable field must be used in every subscription query. It cannot be missing from the query.

  • The indexed queryable field must use an == or IN comparison against a constant at least once in the subscription query. (El campo consultable debe utilizar una comparación o contra una constante al menos una vez en la consulta de suscripción.) For example, user_id == $0, "641374b03725038381d2e1fb" or store_id IN $0, {1,2,3}. (Por ejemplo, o .)

Opcionalmente, puedes incluir una comparación de AND siempre que el campo indexado consultable se compare directamente con una constante usando == o IN al menos una vez. Por ejemplo, store_id IN {1,2,3} AND region=="Northeast" o store_id == 1 AND (active_promotions < 5 OR num_employees < 10).

Invalid Flexible Sync queries on an indexed queryable field include queries where:

  • The indexed queryable field does not use AND with the rest of the query. For example store_id IN {1,2,3} OR region=="Northeast" is invalid because it uses OR instead of AND. Similarly, store_id == 1 AND active_promotions < 5 OR num_employees < 10 is invalid because the AND only applies to the term next to it, not the entire query.

  • El campo consultable indexado no se utiliza en un operador de igualdad. Por ejemplo, store_id > 2 AND region=="Northeast" no es válido porque solo utiliza el operador > con el campo consultable indexado y no tiene una comparación de igualdad.

  • The query is missing the indexed queryable field entirely. For example, region=="Northeast or truepredicate are invalid because they do not contain the indexed queryable field.

Flexible Sync has some limitations when using RQL operators. When you write the query subscription that determines which data to sync, the server does not support these query operators. However, you can still use the full range of RQL features to query the synced data set in the client application.

Tipo de operador
Operadores no compatibles

Aggregate Operators

@avg, @count, @max, @min, @sum

Query Suffixes

DISTINCT, SORT, LIMIT

Las queries que no distinguen entre mayúsculas y minúsculas ([c]) no pueden usar índices de manera eficaz. Como resultado, no se recomiendan las queries que no distinguen entre mayúsculas y minúsculas, ya que podrían provocar problemas de rendimiento.

Flexible Sync only supports @count for array fields.

Flexible Sync admite la consulta de listas usando el operador IN.

Puede consultar una lista de constantes para ver si contiene el valor de un campo consultable:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

If a queryable field has an array value, you can query to see if it contains a constant value:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

Advertencia

You cannot compare two lists with each other in a Flexible Sync query. Note that this is valid Realm Query Language syntax outside of Flexible Sync queries.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

Flexible Sync does not support querying on properties in Embedded Objects or links. For example, obj1.field == "foo".

The size limit for any given query subscription in your subscription set is 256 kB. Exceeding this limit results in a LimitsExceeded Error.

Volver

Configure & Open a Synced Realm

En esta página