Overview
Flexible Sync utiliza suscripciones y permisos para determinar qué datos sincronizar con su aplicación.
Para utilizar Flexible Sync en el SDK:
Autenticar un usuario en su proyecto cliente.
Abra el reino sincronizado con una configuración de sincronización flexible
Puede agregar, actualizar y eliminar suscripciones de consultas para determinar qué datos se sincronizan con el dispositivo cliente.
Tip
Esta página detalla cómo administrar las suscripciones para 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.
Para obtener información sobre cómo configurar permisos para la sincronización flexible, consulte Reglas y permisos de sincronización flexible.
Suscribirse a campos consultables
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 admite todos los operadores disponibles en el lenguaje de consulta Realm. Consulte las limitaciones de Flexible Sync RQL para obtener más información.
Puede:
Añadir suscripciones
Reaccionar al estado de la suscripción
Actualizar suscripciones con nuevas consultas
Remover suscripciones individuales o todas las suscripciones de un tipo de objeto Realm.
Los datos que coinciden con la suscripción, donde el usuario tiene los permisos adecuados, se sincronizan entre los clientes y la aplicación backend.
Puede especificar un nombre de cadena opcional para su suscripción.
Tip
Especifique siempre un nombre de suscripción
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.
Al crear una suscripción, Realm busca datos que coincidan con una consulta sobre un tipo de objeto específico. Puede tener varios conjuntos de suscripciones para distintos tipos de objeto. También puede tener varias consultas sobre el mismo tipo de objeto.
Puedes crear una suscripción con un nombre específico. Luego, puedes buscarla por nombre para actualizarla o eliminarla.
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser()) .initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() { 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() { 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") } })
También puedes buscar suscripciones por consulta. Si omites el nombre al crear una suscripción, esta es la única forma de buscarla.
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser()) .initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() { 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() { 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
Los nombres de las suscripciones deben ser únicos. Agregar una suscripción con el mismo nombre que una existente genera un error.
Si no nombra explícitamente una suscripción y, en cambio, se suscribe a la misma consulta sin nombre más de una vez, Realm no conserva las consultas duplicadas en el conjunto de suscripciones.
Si se suscribe a la misma consulta más de una vez con nombres diferentes, Realm conserva ambas suscripciones en el conjunto de suscripciones.
Añadir una suscripción
Añade una suscripción a un bloque de escritura de suscripciones. Cada nueva suscripción se añade a las suscripciones de Realm del cliente.
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser()) .initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() { 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() { 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
Enlaces de objetos
Debe agregar un objeto y su objeto vinculado al conjunto de suscripciones para ver un objeto vinculado.
Si los resultados de su suscripción contienen un objeto con una propiedad que enlaza a un objeto no incluido en los resultados, el enlace parece nulo. No hay forma de distinguir si el valor de esa propiedad es legítimamente nulo o si el objeto al que enlaza existe, pero no está visible para la suscripción de consulta.
Espere a que los cambios de suscripción se sincronicen
Escribir una actualización local en el conjunto de suscripciones es solo un componente del cambio de una suscripción. Tras el cambio de suscripción local, el cliente se sincroniza con el servidor para resolver cualquier actualización de datos debida al cambio de suscripción. Esto podría implicar añadir o eliminar datos del dominio sincronizado. Utilice el método de compilación waitForInitialRemoteData() para forzar el bloqueo de la aplicación hasta que los datos de la suscripción del cliente se sincronicen con el backend antes de abrir el dominio:
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser()) .initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() { 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() { 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 utilizar SubscriptionSet.waitForSynchronization() o SubscriptionSet.waitForSynchronizationAsync() para retrasar la ejecución hasta que se complete la sincronización de la suscripción después de crear una conexión de sincronización.
Enumeración SubscriptionSet.State
Además, puede supervisar el estado del conjunto de suscripciones con la enumeración SubscriptionSet.State. Puede usar el estado de la suscripción para:
Mostrar un indicador de progreso mientras se descargan los datos
Descubra cuándo se reemplaza un conjunto de suscripciones
Puede acceder al estado del conjunto de suscripciones de su aplicación utilizando SubscriptionSet.getState().
Nota
Estado de suscripción "Completado"
El estado "Completado" del conjunto de suscripción no significa que la sincronización esté completa ni que todos los documentos se hayan sincronizado. "Completado" significa que han ocurrido las dos cosas siguientes:
La suscripción se ha convertido en el conjunto de suscripciones activas que actualmente se está sincronizando con el servidor.
Los documentos que coincidían con la suscripción en el momento de enviarla al servidor se encuentran ahora en el dispositivo local. Tenga en cuenta que esto no incluye necesariamente todos los documentos que coinciden actualmente con la suscripción.
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.
Reemplazado
SUPERSEDED Es un SubscriptionSet.State que puede ocurrir cuando otro subproceso escribe una suscripción en una instancia diferente del conjunto de suscripciones. Si el estado pasa a SUPERSEDED, debe obtener una nueva instancia del conjunto de suscripciones antes de poder escribir en él.
Actualizar suscripciones con una nueva consulta
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() { 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" ) ) ) }
No se pueden actualizar las suscripciones creadas sin nombre. Sin embargo, se pueden buscar suscripciones sin nombre por su consulta, eliminarlas del conjunto de suscripciones y luego agregar una nueva suscripción con una consulta actualizada:
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() { 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" ) ) ) }
Eliminar suscripciones
Para eliminar suscripciones, puedes:
Eliminar una sola consulta de suscripción
Eliminar todas las suscripciones a un tipo de objeto específico
Eliminar todas las suscripciones
Cuando elimina una consulta de suscripción, Realm elimina de forma asincrónica los datos sincronizados que coinciden con la consulta del dispositivo cliente.
Eliminar una sola suscripción
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() { 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) }
Eliminar todas las suscripciones a un tipo de objeto Realm
Si desea eliminar todas las suscripciones a un tipo de objeto específico, pase una clase al método removeAll():
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() { public void update(MutableSubscriptionSet subscriptions) { subscriptions.removeAll(Frog.class); } });
realm.subscriptions.update { subscriptions -> subscriptions.removeAll( Frog::class.java ) }
Eliminar todas las suscripciones
Para eliminar todas las suscripciones del conjunto de suscripciones, utilice removeAll() sin argumentos:
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() { public void update(MutableSubscriptionSet subscriptions) { subscriptions.removeAll(); } });
realm.subscriptions.update { subscriptions -> subscriptions.removeAll() }
Requisitos y limitaciones de RQL de sincronización flexible
Requisitos de suscripción a campos consultables indexados
Añadir un campo consultable indexado a tu aplicación puede mejorar el rendimiento de consultas simples sobre datos con particiones estrictas. Por ejemplo, una aplicación donde las consultas asignan datos de forma estricta a un dispositivo, tienda o usuario,user_id == $0, “641374b03725038381d2e1fb” como, es una buena candidata para un campo consultable indexado. Sin embargo, un campo consultable indexado tiene requisitos específicos para su uso en una suscripción de consultas:
El campo consultable indexado debe usarse en todas las consultas de suscripción. No puede faltar en la consulta.
El campo consultable indexado debe usar una comparación
==oINcon una constante al menos una vez en la consulta de suscripción. Por ejemplo,user_id == $0, "641374b03725038381d2e1fb"ostore_id IN $0, {1,2,3}.
Opcionalmente, puede incluir una comparación AND siempre que el campo consultable indexado 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).
Las consultas de sincronización flexibleno válidas en un campo consultable indexado incluyen consultas donde:
El campo consultable indexado no usa
ANDcon el resto de la consulta. Por ejemplo,store_id IN {1,2,3} OR region=="Northeast"no es válido porque usaORen lugar deAND. De igual manera,store_id == 1 AND active_promotions < 5 OR num_employees < 10no es válido porqueANDsolo se aplica al término contiguo, no a toda la consulta.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.A la consulta le falta por completo el campo consultable indexado. Por ejemplo,
region=="Northeastotruepredicateno son válidos porque no contienen dicho campo.
Operadores de consulta no admitidos en Flexible Sync
La sincronización flexible presenta algunas limitaciones al usar operadores RQL. Al escribir la suscripción de consulta que determina qué datos sincronizar, el servidor no admite estos operadores. Sin embargo, aún puede usar todas las funciones de RQL para consultar el conjunto de datos sincronizados en la aplicación cliente.
Tipo de operador | Operadores no compatibles |
|---|---|
Operadores agregados |
|
Sufijos de consulta |
|
Las consultas que no distinguen entre mayúsculas y minúsculas ([c]) no pueden usar índices eficazmente. Por lo tanto, no se recomiendan, ya que podrían causar problemas de rendimiento.
Flexible Sync solo admite @count para campos de matriz.
Consultas de lista
Flexible Sync admite la consulta de listas mediante 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 }"
Si un campo consultable tiene un valor de matriz, puedes consultar para ver si contiene un valor constante:
// Query an array-valued queryable field for a constant value "'comedy' IN genres"
Advertencia
No se pueden comparar dos listas en una consulta de sincronización flexible. Tenga en cuenta que esta sintaxis del lenguaje de consulta de dominio es válida fuera de las consultas de sincronización flexible.
// 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"
Objetos incrustados o vinculados
La sincronización flexible no admite consultas sobre propiedades en objetos incrustados ni enlaces. Por ejemplo, obj1.field == "foo".
Límite de tamaño de consulta
El límite de tamaño para cualquier suscripción de consulta en su conjunto de suscripciones es de kB. Superar este límite genera 256 un error "LimitsExceeded".