Docs Menu
Docs Home
/ /
Sincronizar datos

Administrar suscripciones de sincronización - SDK de Node.js

Flexible Sync usa suscripciones y permisos para determinar qué datos sincronizar con tu app. Debes tener al menos una suscripción para poder leer o escribir en un dominio con Flexible Sync habilitado. Esta página detalla cómo administrar esas suscripciones.

Puedes agregar, actualizar y eliminar suscripciones de consultas para controlar qué datos se sincronizan con el dispositivo cliente. En el SDK de Node.js de Realm v12.0.0 y versiones posteriores, puedes suscribirte a consultas en lugar de administrar las suscripciones manualmente, o además de hacerlo.

No puedes crear suscripciones para Ingesta de datos y objetos asimétricos porque solo envían datos al backend de su aplicación.

Importante

Limitaciones de las consultas de sincronización flexible

Las suscripciones de sincronización flexible solo admiten un subconjunto de operadores de consulta RQL. Consulte la documentación sobre las limitaciones de RQL de sincronización flexible para obtener información sobre los operadores no compatibles.

Debe cumplir los siguientes requisitos antes de poder utilizar Atlas Device Sync con el SDK de Node.js:

Además de los requisitos, debe configurar lo siguiente para usar Flexible Sync en un cliente Node.js:

  1. Configurar sincronización flexible en el backend.

  2. Inicializa la aplicación.

  3. Autenticar un usuario en su proyecto cliente.

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

Nuevo en la versión 12.0.0.

Realm Node.js v12.0.0 añade APIs experimentales que se suscriben y desuscriben de los resultados de una query. Estas API abstraen los detalles de añadir y remover suscripciones manualmente.

Para todas las suscripciones, necesita un usuario autenticado y un reino de sincronización flexible.

Cambiado en la 12.3.0 versión: Datos geoespaciales compatibles con Atlas Device Sync

En el SDK de Realm Node.js v12.3.0 y versiones posteriores, puede crear suscripciones a consultas geoespaciales. Si intenta suscribirse a una consulta geoespacial con una versión anterior del SDK, recibirá un error de servidor con una escritura compensatoria.

Para obtener más información, consulte Consulta de datos geoespaciales.

Le recomendamos que asigne un nombre a sus suscripciones. Esto facilita su búsqueda y gestión. Los nombres de las suscripciones deben ser únicos. Intentar agregar una suscripción con el mismo nombre que una ya existente genera un error.

Para suscribirse a una consulta:

  1. Consulta los objetos que quieres leer y escribir.

  2. Llamar subscribe() en los resultados de la consulta para crear una suscripción de sincronización para los objetos que coincidan con la consulta.

  3. Pase un objeto SubscriptionOptions que contenga la propiedad name a subscribe().

const subOptions = {
name: "All completed tasks",
};
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe(subOptions);
const completedTasksSubscription = realm.subscriptions.findByName(
"All completed tasks"
);
// ...work with the subscribed results list or modify the subscription
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe({ name: "All completed tasks" });
const completedTasksSubscription = realm.subscriptions.findByName(
"All completed tasks"
);
// ...work with the subscribed results list or modify the subscription

Generalmente, deberías asignar un nombre a tus suscripciones. Si no, el nombre se establece como nulo.

Si usa filtered() en una suscripción de consulta sin nombre, el identificador de la suscripción se basa en la consulta filtered. Esto significa que cada vez que cambie la cadena de consulta, subscribe() creará una nueva suscripción.

const config = {
schema: [Task],
sync: {
user: app.currentUser,
flexible: true,
},
};
const realm = await Realm.open(config);
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe();
// ...work with the subscribed results list
const config: Realm.Configuration = {
schema: [Task],
sync: {
user: app.currentUser!,
flexible: true,
},
};
const realm = await Realm.open(config);
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe();
// ...work with the subscribed results list

Al suscribirse a los resultados de una consulta, estos no contienen objetos hasta que se descargan los datos sincronizados. Si necesita esperar a que los objetos sincronizados terminen de descargarse, utilice waitForSync. Puede especificar diferentes comportamientos para sus suscripciones y cómo gestionan la escritura de las descargas.

Este ejemplo utiliza la opción FirstTime, que es el comportamiento predeterminado. Una suscripción con el comportamiento FirstTime solo espera a que finalice la sincronización al crearse la suscripción.

import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Only waits for sync to finish on the initial sync.
await completedTasks.subscribe({
behavior: WaitForSync.FirstTime,
name: "First time sync only",
});

Las otras opciones admitidas WaitForSync son:

  • Always: Espera a que se descarguen los objetos coincidentes cada vez que se inicia la aplicación. La aplicación debe tener conexión a internet cada vez que se inicia.

  • NeverNo esperes para descargar los objetos coincidentes. La aplicación necesita conexión a internet para que el usuario se autentique la primera vez que se inicia, pero puede abrirse sin conexión en los siguientes inicios usando credenciales en caché.

Opcionalmente, puede especificar un valor timeout para limitar el tiempo que dura la descarga sincronizada:

import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Add subscription with timeout
// If timeout expires before sync is completed, currently-downloaded
// objects are returned and sync download continues in the background.
const taskSubscription = await completedTasks.subscribe({
behavior: WaitForSync.Always,
timeout: 500,
});

Para cancelar la suscripción a los resultados de una query utilizando unsubscribe():

import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Only waits for sync to finish on the initial sync.
await completedTasks.subscribe({
behavior: WaitForSync.FirstTime,
name: "First time sync only",
});
// Unsubscribe
completedTasks.unsubscribe();

Esto elimina la suscripción de la lista de suscripciones activas, de forma similar a eliminar una suscripción manualmente.

Una lista de resultados aún puede contener objetos después de llamar a unsubscribe() si existe otra suscripción que contiene objetos superpuestos.

Al llamar a unsubscribe(), se elimina la suscripción asociada. Las suscripciones se eliminan por nombre. Si no tienen nombre, unsubscribe() elimina cualquier consulta que coincida exactamente con la consulta en la que se llama a unsubscribe().

El método unsubscribe() regresa antes de que se eliminen del dominio los objetos que coinciden con la suscripción eliminada. La sincronización continúa en segundo plano según el nuevo conjunto de suscripciones.

Puede utilizar la API de suscripciones para administrar manualmente un conjunto de suscripciones a consultas específicas en campos consultables.

Puede:

  • Obtenga una lista de todas las suscripciones

  • Añadir suscripciones

  • Comprobar el estado de la suscripción

  • Actualizar suscripciones con nuevas consultas

  • Eliminar suscripciones individuales o todas las suscripciones de un tipo

Cuando los datos coinciden con la suscripción y tienen los permisos adecuados, se sincronizan entre los dispositivos y la aplicación backend.

Al crear una suscripción, Realm busca datos que coincidan con una consulta sobre un tipo de objeto específico. Puede tener suscripciones para varios tipos de objeto. También puede tener varias consultas sobre el mismo tipo de objeto.

Importante

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.

Al utilizar un reino sincronizado flexible, puede acceder SubscriptionSet a, una colección de suscripciones, a través de la propiedad realm.subscriptions.

// get the SubscriptionSet for the realm
const subscriptions = realm.subscriptions;

Las suscripciones se basan en los resultados de las consultas de reino.

En el siguiente ejemplo, se han establecido completed y progressMinutes como campos consultables en una aplicación de App Services. En el código del cliente, creamos consultas filtradas y luego nos suscribimos a sus resultados:

  • Tareas completadas

  • Tareas completadas que han ocupado 120 progressMinutes

const tasks = realm.objects("Task");
const longRunningTasks = tasks.filtered(
'status == "completed" && progressMinutes > 120'
);
await realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(longRunningTasks, {
name: "longRunningTasksSubscription",
});
mutableSubs.add(realm.objects("Team"), {
name: "teamsSubscription",
});
});

Debes tener al menos una suscripción para poder leer o escribir en un reino de sincronización flexible. Puedes añadir una suscripción inicial al abrir un reino.

Para initialSubscriptions configurar las suscripciones iniciales, incluya el campo en la configuración de sincronización de su dominio. Dentro del initialSubscriptions objeto, agregue un update campo configurado para una devolución de llamada que se suscriba a las consultas:

const config = {
schema: [Task],
sync: {
user: app.currentUser,
flexible: true,
initialSubscriptions: {
update: (subs, realm) => {
subs.add(realm.objects(Task).filtered("status == 'in progress'"), {
name: "In progress tasks",
});
},
rerunOnOpen: true,
},
},
};
const realm = await Realm.open(config);
const config: Realm.Configuration = {
schema: [Task],
sync: {
user: app.currentUser!,
flexible: true,
initialSubscriptions: {
update: (subs, realm) => {
subs.add(realm.objects(Task).filtered("status == 'in progress'"), {
name: "In progress tasks",
});
},
rerunOnOpen: true,
},
},
};
const realm = await Realm.open(config);

De forma predeterminada, las suscripciones iniciales solo se crean la primera vez que se abre un reino. Si su aplicación necesita volver a ejecutar esta suscripción inicial cada vez que se inicia, puede establecer rerunOnOpen en true. Podría ser necesario hacerlo para volver a ejecutar intervalos de tiempo dinámicos u otras consultas que requieran volver a calcular las variables estáticas de la suscripción.

Puede comprobar el estado de la suscripción para ver si el servidor ha reconocido la suscripción y el dispositivo ha descargado los datos localmente.

Puede utilizar el estado de suscripción para:

  • Manejo de errores de activación

  • Mostrar si la transacción está pendiente o se ha completado

  • Descubre cuándo se reemplaza un conjunto de suscripciones y deberías obtener una nueva instancia del conjunto de suscripciones para guardar un cambio de suscripción.

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.

Nuevo en la versión 12.0.0.

Node.js v12.0.0 agregó la enumeración SubscriptionSetState que puede usar para obtener el estado de una suscripción.

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.

Puede actualizar una suscripción con nombre mediante una nueva consulta. Para actualizar la consulta de una suscripción, pase la nueva consulta y una opción de suscripción con el nombre de la suscripción que desea actualizar al método MutableSubscriptionSet.add(). Al igual que al añadir una nueva suscripción, debe actualizarla dentro de una transacción llamando a subscriptions.update().

En el siguiente ejemplo, las tareas de larga ejecución se redefinen como cualquier tarea que haya tomado más de 180 minutos.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(
tasks.filtered('status == "completed" && progressMinutes > 180'),
{
name: "longRunningTasksSubscription",
}
);
});

Nota

Intentar actualizar una suscripción que tiene el campo SubscriptionOptions.throwOnUpdate establecido como verdadero genera una excepción.

Puedes eliminar suscripciones de varias maneras:

  • Eliminar una sola suscripción con una consulta específica

  • Eliminar una sola suscripción con un nombre específico

  • Eliminar todas las suscripciones a un modelo de objeto específico

  • Remover todas las suscripciones sin nombre

  • Eliminar todas las suscripciones

Cuando elimina una consulta de suscripción, el servidor también elimina los datos sincronizados del dispositivo cliente.

Puede eliminar una suscripción específica mediante una consulta ejecutando una transacción en el conjunto de suscripciones. Pase la consulta al método remove() en el MutableSubscriptionSet dentro de una transacción.

En el siguiente ejemplo, la suscripción a las tareas con un propietario llamado "Ben" se elimina del conjunto de suscripciones.

realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific query
mutableSubs.remove(tasks.filtered('owner == "Ben"'));
});

Para eliminar una suscripción específica por nombre, ejecute una transacción en el conjunto de suscripciones. Dentro de la transacción, pase el nombre al método removeByName() MutableSubscriptionSet en.

realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific name
mutableSubs.removeByName("longRunningTasksSubscription");
});

Si tiene una referencia a una suscripción, puede eliminarla. Para ello, ejecute una transacción en el conjunto de suscripciones. Dentro de la transacción, pase la variable de referencia al método removeSubscription MutableSubscriptionSet en.

let subscriptionReference;
realm.subscriptions.update((mutableSubs) => {
subscriptionReference = mutableSubs.add(realm.objects("Task"));
});
// later..
realm.subscriptions.removeSubscription(subscriptionReference);

Para eliminar todas las suscripciones de un tipo de objeto específico, ejecute una transacción en el conjunto de suscripciones. Dentro de la transacción, pase el tipo de objeto como una cadena al método removeByObjectType MutableSubscriptionSet en.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeByObjectType("Team");
});

Novedad en la versión12.0.0 v.

Es posible que desee eliminar las suscripciones sin nombre que son transitorias o generadas dinámicamente, pero dejar las suscripciones con nombre en su lugar.

Puede eliminar todas las suscripciones sin nombre del conjunto de suscripciones llamando a .removeUnnamed() en mutableSubs. .removeUnnamed() devuelve la cantidad de suscripciones sin nombre eliminadas.

// Remove unnamed subscriptions.
let numberRemovedSubscriptions = 0;
await realm.subscriptions.update((mutableSubs) => {
numberRemovedSubscriptions = mutableSubs.removeUnnamed();
});

Para eliminar todas las suscripciones del conjunto, ejecute una transacción en dicho conjunto. Llame a removeAll() en el MutableSubscriptionSet dentro de la transacción.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeAll();
});

Administrar múltiples suscripciones con las subscribe() unsubscribe() API y descritas en la sección Suscribirse a consultas es menos eficiente que realizar actualizaciones por lotes cuando administra las suscripciones manualmente.

Para un mejor rendimiento al realizar varios cambios en las suscripciones, use la subscriptions API para actualizar todas las suscripciones en una sola transacción. Para saber cómo, consulte "Administrar suscripciones manualmente".

Cada transacción de escritura para un conjunto de suscripciones tiene un coste de rendimiento. Si necesita realizar varias actualizaciones a un objeto de Realm durante una sesión, considere mantener los objetos editados en memoria hasta que se completen todos los cambios. Esto mejora el rendimiento de la sincronización al escribir solo el objeto completo y actualizado en su reino, en lugar de cada cambio.

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 == o IN con una constante al menos una vez en la consulta de suscripción. Por ejemplo, user_id == $0, "641374b03725038381d2e1fb" o store_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 AND con el resto de la consulta. Por ejemplo, store_id IN {1,2,3} OR region=="Northeast" no es válido porque usa OR en lugar de AND. De igual manera, store_id == 1 AND active_promotions < 5 OR num_employees < 10 no es válido porque AND solo 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=="Northeast o truepredicate no son válidos porque no contienen dicho campo.

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

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

Sufijos de consulta

DISTINCT, SORT, LIMIT

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.

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"

La sincronización flexible no admite consultas sobre propiedades en objetos incrustados ni enlaces. Por ejemplo, obj1.field == "foo".

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".

Volver

Configurar y abrir un reino sincronizado