Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Managed assinaturas de sincronização - Node.js SDK

Nesta página

  • Pré-requisitos
  • Inscrever-se para receber queries
  • Inscrever-se em uma query
  • Assinar uma query sem um nome de assinatura
  • Aguarde uma assinatura de query para sincronizar
  • Cancelar assinatura de uma query
  • Gerenciar assinaturas manualmente
  • Obter todas as assinaturas
  • Adicionar uma assinatura
  • Definir assinaturas iniciais
  • Verifique o status das assinaturas
  • Estado da assinatura "Concluído"
  • Atualizar assinaturas com uma nova query
  • Remover subscrições
  • Remover uma assinatura por query
  • Remover uma assinatura por nome
  • Remover uma assinatura por referência
  • Remover todas as assinaturas de um tipo de objeto
  • Remover todas as assinaturas sem nome
  • Remover todas as assinaturas
  • Considerações de desempenho
  • Eficiência da API
  • Atualizações de grupo para melhorar o desempenho
  • Requisitos e limitações do Flexible Sync RQL
  • Requisitos de inscrição de campos de query indexados
  • Operadores de consulta não suportados na sincronização flexível
  • Listar queries
  • Objetos incorporados ou vinculados
  • Limite de tamanho da query

O Flexible Sync usa assinaturas e permissões para determinar quais dados sincronizar com seu aplicativo. Você deve ter pelo menos uma assinatura antes de ler ou escrever em um Realm com o Flexible Sync habilitado. Esta página detalha como managed essas assinaturas.

Você pode adicionar, atualizar e remover assinaturas de query para controlar quais dados são sincronizados com o dispositivo cliente. No Realm Node.js SDK v12.0.0 e posterior, você pode assinar query em vez de gerenciar manualmente as assinaturas ou além delas.

Você não pode criar assinaturas para a ingestão dedados e objetos assimétricos porque eles só enviam dados para o backend do seu aplicativo.

Importante

Limitações de query do Flexible Sync

As assinaturas do Flexible Sync oferecem suporte apenas a um subconjunto dos operadores de query RQL. Consulte a documentação Flexible Sync RQL das Limitações de do para obter informações sobre quais operadores não são suportados.

Você precisa atender aos seguintes requisitos antes de poder usar o Realm Mobile Sync com o Node.js SDK:

Além dos requisitos, você precisa configurar o seguinte para usar o Flexible Sync em um cliente Node.js:

  1. Configure o Flexible Sync no backend.

  2. Inicialize o aplicativo.

  3. Autenticar um usuário em seu projeto de cliente.

  4. Abra o Realm sincronizado com uma configuração Flexible Sync

Novo na versão 12.0.0.

O Realm Node.js v12.0.0 adiciona API experimentais que se inscrevem e cancelam a assinatura dos resultados de uma query. Essas API resumem os detalhes de adicionar e remover assinaturas manualmente.

Para todas as assinaturas, você precisa de um usuário autenticado e um termo do Flexible Sync.

Alterado na versão 12,3,0: Dados geoespaciais suportados no Atlas Device Sync

No Realm Node.js SDK v12.3.0 e posterior, você pode criar query para queries geoespaciais. Se você tentar se inscrever em uma query geoespacial com uma versão mais antiga do SDK, receberá um erro de servidor com uma gravação compensatória.

Para mais informações, consulte query de Dados Geoespaciais.

Recomendamos que você nomeie suas assinaturas. Isso torna mais fácil encontrar e gerenciar suas assinaturas. Os nomes das assinaturas devem ser exclusivos. Tentando adicionar uma assinatura com o mesmo nome de uma assinatura existente exibe um erro.

Para assinar uma query:

  1. Consulte os objetos que você deseja ler e gravar.

  2. Ligue subscribe() nos resultados da query para criar uma assinatura de sincronização para objetos correspondentes à query.

  3. Passe um objeto SubscriptionOptions que contenha a propriedade name para 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

Na maioria das vezes, você deve dar um nome às suas assinaturas. Caso contrário, o nome será definido como nulo.

Se você usar filtered() em uma assinatura de query sem nome, o identificador de assinatura será baseado na query filtered. Isto significa que toda vez que sua string de query for alterada, o subscribe() criará uma nova assinatura.

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

Quando você assina os resultados de uma query, os resultados não contêm objetos até que os dados sincronizados sejam baixados. Quando for necessário aguardar o término do download dos objetos sincronizados, use waitForSync. Você pode especificar um comportamento diferente para suas assinaturas e como elas lidam com o Witing para downloads.

Este exemplo utiliza a opção FirstTime , que é o comportamento padrão. Uma assinatura com comportamento FirstTime somente aguarda a sincronização terminar quando uma assinatura é criada pela primeira vez.

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",
});

As outras opções WaitForSync suportadas são:

  • Always: Aguarde o download dos objetos correspondentes toda vez que seu aplicativo for iniciado. O aplicativo deve ter uma conexão com a Internet em cada lançamento.

  • Never: Nunca espere para baixar objetos correspondentes. O aplicativo precisa de uma conexão com a Internet para que o usuário se autentique na primeira vez que o aplicativo for iniciado, mas pode ser aberto off-line nas inicializações subsequentes usando credenciais em cache.

Opcionalmente, você pode especificar um valor timeout para limitar quanto tempo o download de sincronização é executado:

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,
});

Você pode cancelar a assinatura dos resultados de uma query usando 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();

Isso remove a assinatura da lista de assinaturas ativas, semelhante à remoção manual de uma assinatura.

Uma lista de resultados ainda pode conter objetos após ligar para unsubscribe() se houver outra assinatura que contenha objetos sobrepostos.

Quando você chama unsubscribe(), a assinatura associada é removida. As assinaturas são removidas por nome. Se eles não tiverem um nome, unsubscribe() remove todas as queries que correspondam exatamente à que você chama unsubscribe().

O método unsubscribe() retorna antes que os objetos correspondentes à assinatura removida sejam excluídos do domínio. A sincronização continua em segundo plano com base no novo conjunto de assinaturas.

Você pode usar a API de Assinaturas para gerenciar manualmente um conjunto de assinaturas para queries específicas em campos consultáveis.

Você pode:

  • Obter uma lista de todas as assinaturas

  • Adicionar subscrições

  • Verificar estado da assinatura

  • Atualizar assinaturas com novas queries

  • Remover assinaturas individuais ou todas as assinaturas de um tipo

Quando os dados correspondem à assinatura e têm permissões apropriadas, eles são sincronizados entre os dispositivos e o aplicativo de backend.

Quando você cria uma assinatura, o Realm procura dados correspondentes a uma query em um tipo de objeto específico. Você pode ter assinaturas em vários tipos de objetos diferentes. Você também pode ter várias queries no mesmo tipo de objeto.

Importante

Links de objetos

Você deve adicionar um objeto e seu objeto vinculado ao conjunto de assinaturas para ver um objeto vinculado.

Se os resultados de sua assinatura contiverem um objeto com uma propriedade vinculada a um objeto não contido nos resultados, o link parecerá nulo. Não há como distinguir se o valor dessa propriedade é legitimamente nulo ou se o objeto ao qual ela se vincula existe, mas está fora da exibição da assinatura de query..

Ao usar um domínio sincronizado flexível, você pode acessar um SubscriptionSet, uma coleção de assinaturas, por meio do realm.subscriptions propriedade.

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

As assinaturas são baseadas nos resultados das query do Realm.

No exemplo seguinte, completed e progressMinutes foram definidos como campos consultáveis em um aplicativo do App Services. No código do cliente, criamos queries filtradas e, em seguida, assinamos seus resultados:

  • Tarefas concluídas

  • Tarefas concluídas que assumiram mais de 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",
});
});

Você deve ter pelo menos uma assinatura antes de ler ou escrever em um Realm Flexible Sync. Você pode adicionar uma assinatura inicial ao abrir um Realm.

Para definir as assinaturas iniciais, inclua o campo initialSubscriptions na SyncConfiguration do seu domínio. Dentro do objeto initialSubscriptions , adicione um campo update definido para uma chamada de resposta que se inscreve nas 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);

Por padrão, as assinaturas iniciais são criadas somente na primeira vez que um domínio é aberto. Se seu aplicativo precisar executar novamente essa assinatura inicial toda vez que o aplicativo for iniciado, você poderá definir rerunOnOpen como true. Talvez você precise fazer isso para executar novamente intervalos de tempo dinâmicos ou outras queries que exijam um novo cálculo de variáveis estáticas para a assinatura.

Você pode verificar o estado da assinatura para ver se o servidor reconheceu a assinatura e se o dispositivo baixou os dados localmente.

Você pode usar o estado da assinatura para:

  • Trigger error handling

  • Mostrar se a transação está pendente ou foi concluída

  • Descubra quando um conjunto de assinaturas é substituído e você deve obter uma nova instância do conjunto de assinaturas para gravar uma alteração de assinatura

Observação

Estado da assinatura "Concluído"

O estado do conjunto de assinaturas "complete" não significa que a sincronização "está concluída" ou "todos os documentos foram sincronizados". "Completo" significa que as duas coisas a seguir aconteceram:

  • A assinatura se tornou o conjunto de assinaturas ativo que está sendo atualmente sincronizado com o servidor.

  • Os documentos que correspondiam à assinatura no momento em que a assinatura foi enviada ao servidor agora estão no dispositivo local. Observe que isso não inclui necessariamente todos os documentos que atualmente correspondem à assinatura.

O SDK do Realm não fornece uma maneira de verificar se todos os documentos que correspondem a uma assinatura foram sincronizados com o dispositivo.

Novo na versão 12.0.0.

Node.js v12.0.0 adicionou o SubscriptionSetState enum que você pode usar para obter o status de uma assinatura.

O estado do conjunto de assinaturas "complete" não significa que a sincronização "está concluída" ou "todos os documentos foram sincronizados". "Completo" significa que as duas coisas a seguir aconteceram:

  • A assinatura se tornou o conjunto de assinaturas ativo que está sendo atualmente sincronizado com o servidor.

  • Os documentos que correspondiam à assinatura no momento em que a assinatura foi enviada ao servidor agora estão no dispositivo local. Observe que isso não inclui necessariamente todos os documentos que atualmente correspondem à assinatura.

O SDK do Realm não fornece uma maneira de verificar se todos os documentos que correspondem a uma assinatura foram sincronizados com o dispositivo.

Você pode atualizar uma assinatura nomeada com uma nova query. Para atualizar a query de uma assinatura, passe a nova query e uma opção de assinatura com o nome da assinatura que você deseja atualizar para o método MutableSubscriptionSet.add() . Como adicionar uma nova assinatura, você deve atualizar uma assinatura dentro de uma transação ligando para subscriptions.update().

No exemplo a seguir, as tarefas de longa duração são redefinidas como quaisquer tarefas que levaram mais de 180 minutos.

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

Observação

A tentativa de atualizar uma assinatura que tenha o campo SubscriptionOptions.throwOnUpdate definido como true gera uma exceção.

Você pode remover assinaturas de várias maneiras:

  • Remover uma única assinatura com uma query específica

  • Remover uma única assinatura com um nome específico

  • Remover todas as assinaturas de um modelo de objeto específico

  • Remover todas as assinaturas sem nome

  • Remover todas as assinaturas

Quando você remove uma query de assinatura, o servidor também remove os dados sincronizados do dispositivo cliente.

Você pode remover uma assinatura específica por query executando uma transação no conjunto de assinaturas. Passe a query para o método remove() no MutableSubscriptionSet dentro de uma transação.

No exemplo a seguir, a assinatura de tarefas com um proprietário chamado 'Ben' é removida do conjunto de assinaturas.

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

Para remover uma assinatura específica por nome, execute uma transação no conjunto de assinaturas. Dentro da transação, passe o nome para o método removeByName() no MutableSubscriptionSet.

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

Se você tiver uma referência a uma assinatura, poderá removê-la. Para isso, execute uma transação no conjunto de assinaturas. Dentro da transação, passe a variável de referência para o método removeSubscription no MutableSubscriptionSet.

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

Para remover todas as assinaturas de um tipo de objeto específico, execute uma transação no conjunto de assinaturas. Na transação, passe o tipo de objeto como uma string para o método removeByObjectType no MutableSubscriptionSet.

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

Novo na versão v12.0.0.

Você pode querer remover assinaturas não nomeadas que são transitórias ou geradas dinamicamente, mas deixar assinaturas nomeadas em vigor.

Você pode remover todas as assinaturas sem nome da assinatura definida ligando para .removeUnnamed() em mutableSubs. .removeUnnamed() retorna o número de assinaturas sem nome removidas.

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

Para remover todas as assinaturas do conjunto de assinaturas, execute uma transação no conjunto de assinaturas. Chame removeAll() no MutableSubscriptionSet dentro da transação

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

O gerenciamento de várias assinaturas com as APIs subscribe() e unsubscribe() descritas na seção Assinar queries é menos eficiente do que executar atualizações em lote quando você gerencia assinaturas manualmente.

Para obter melhor desempenho ao fazer várias alterações na assinatura, use a API subscriptions para atualizar todas as assinaturas em uma única transação. Para saber como, consulte Gerenciar assinaturas manualmente.

Cada transação de escrita para um conjunto de assinaturas tem um custo de desempenho. Se você precisar fazer várias atualizações em um objeto do Realm durante uma sessão, considere manter objetos editados na memória até que todas as alterações sejam concluídas. Isso melhora o desempenho da sincronização, gravando apenas o objeto completo e atualizado em seu domínio, em vez de cada alteração.

Adicionar um campo de query indexado à sua aplicação pode melhorar o desempenho de queries simples em dados fortemente particionados. Por exemplo, uma aplicação onde as queries mapeiam fortemente os dados para um dispositivo, armazém ou usuário, como user_id == $0, “641374b03725038381d2e1fb”, é uma boa candidata para um campo de query indexado. No entanto, um campo de query indexado tem requisitos específicos para uso em uma inscrição de query:

  • O campo de query indexado deve ser usado em todas as inscrições de query. Não pode estar faltando na query.

  • O campo de query indexado deve usar uma comparação == ou IN com uma constante pelo menos uma vez na query de inscrição. Por exemplo, user_id == $0, "641374b03725038381d2e1fb" ou store_id IN $0, {1,2,3}.

Opcionalmente, você pode incluir uma comparação AND, desde que o campo consultável indexado seja comparado diretamente com uma constante usando == ou IN pelo menos uma vez. Por exemplo, store_id IN {1,2,3} AND region=="Northeast" ou store_id == 1 AND (active_promotions < 5 OR num_employees < 10).

As consultas inválidas do Flexible Sync em um campo indexado que pode ser consultado incluem consultas em que:

  • O campo de consulta indexado não utiliza AND com o resto da consulta. Por exemplo store_id IN {1,2,3} OR region=="Northeast" é inválido porque usa OR em vez de AND. Da mesma forma, store_id == 1 AND active_promotions < 5 OR num_employees < 10 é inválido porque o AND só se aplica ao termo ao lado, não à consulta inteira.

  • O campo de consulta indexado não é utilizado em um operador de igualdade. Por exemplo store_id > 2 AND region=="Northeast" é inválido porque utiliza apenas o operador > com o campo de consulta indexado e não tem uma comparação de igualdade.

  • A query está totalmente ausente do campo de query indexado. Por exemplo, region=="Northeast ou truepredicate são inválidos porque não contêm o campo de query indexado.

A Flexible Sync tem algumas limitações ao usar operadores RQL. Quando você escreve a assinatura de consulta que determina quais dados sincronizar, o servidor não oferece suporte a esses operadores de consulta. No entanto, você ainda pode usar toda a gama de recursos de RQL para consultar o conjunto de dados sincronizado no aplicativo cliente.

Tipo de operador
Operadores não suportados
Operadores agregados
@avg, @count, @max, @min, @sum
Sufixos de query
DISTINCT, SORT , LIMIT

Queries que não diferenciam maiúsculas de minúsculas ([c]) não podem usar índices de forma eficaz. Sendo assim, queries que não diferenciam maiúsculas de minúsculas não são recomendadas, pois podem causar problemas de desempenho.

A sincronização flexível suporta apenas @count para campos de array.

A sincronização flexível oferece suporte às listas de query usando o operador IN .

Você pode consultar uma lista de constantes para ver se ela contém o valor de um campo de consulta:

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

Se um campo de query tiver um valor de array, você poderá consultar para ver se ele contém um valor constante:

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

Aviso

Não é possível comparar duas listas entre si em uma consulta de sincronização flexível. Observe que esta é uma sintaxe válida do Realm Query Language fora das consultas do Flexible Sync.

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

A sincronização Flexível não oferece suporte à consulta de propriedades em objetos ou links embarcados. Por exemplo, obj1.field == "foo".

O limite de tamanho para qualquer assinatura de query em seu conjunto de assinaturas é de 256 kB. Exceder esse limite resulta em um erro de LimitsExceeded.

Voltar

Configurar e abrir um domínio sincronizado