Gerencie assinaturas Flexible Sync - Swift SDK
Nesta página
- Visão geral
- Assinaturas
- Assine tipos de objetos
- Permissões
- Gerencie assinaturas em seu aplicativo cliente
- Sobre os exemplos nesta página
- Inscrever-se para receber queries
- Inscrever-se em uma query
- Assinar uma query com um nome de assinatura
- Aguarde uma assinatura de query para sincronizar
- Cancelar assinatura de uma query
- Assinar uma query confinada ao ator
- Gerenciar assinaturas manualmente
- Adicionar uma assinatura
- Aguarde as alterações na assinatura para sincronizar
- Estado do conjunto de assinaturas
- Atualizar assinaturas com uma nova query
- Remover subscrições
- 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
Visão geral
Novidades na versão 10.22.0.
Flexible Sync usa assinaturas e permissões para determinar quais dados sincronizar com seu aplicativo.
Para usar Flexible Sync em um cliente iOS:
Autenticar um usuário em seu projeto de cliente.
Abra o Realm sincronizado com uma configuração Flexible Sync
Você pode adicionar, atualizar e remover assinaturas manualmente para determinar quais dados são sincronizados com o dispositivo cliente. No Realm Swift SDK versão 10.43.0 e posterior, você pode assinar queries em vez de ou além de gerenciar assinaturas manualmente.
Dica
O Flexible Sync suporta Combine.
Assinaturas
Ao configurar o Flexible Sync no backend, você especifica quais campos seu aplicativo cliente pode executar uma query usando assinaturas.
Cada assinatura corresponde a uma query em campos desejáveis para um tipo de objeto específico. Consulte Campos consultáveis na documentação do Atlas App Services para obter mais informações.
Para cada assinatura de query, o Realm procura dados correspondentes à query. Os dados correspondentes à assinatura, nos quais o usuário tem as permissões apropriadas, são sincronizados entre os clientes e o aplicativo de backend.
Você pode construir queries com o mecanismo de query do Realm Swift SDK.
Assine tipos de objetos
Os conjuntos de assinaturas são baseados no tipo de objeto. Você pode ter várias assinaturas se tiver muitos tipos de objetos do Realm. Você também pode ter várias assinaturas no mesmo tipo de objeto.
No entanto, observe o seguinte se você usar relacionamentos ou objetos assimétricos em seu aplicativo:
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 está vinculada existe, mas está fora da visão da assinatura da query.
Objetos assimétricos
Se o seu aplicativo usar a ingestão de dados para sincronizar unidirecionalmente objetos assimétricos, você não poderá criar assinaturas para esses objetos. Se seu aplicativo contiver objetos assimétricos e objetos não assimétricos no mesmo território, você poderá adicionar queries de assinatura do Flexible Sync para os objetos não assimétricos.
Permissões
As assinaturas funcionam lado a lado com as permissões para determinar quais dados devem ser sincronizados com seu aplicativo cliente. O aplicativo cliente só vê o subconjunto de dados que corresponde às suas assinaturas, que também corresponde às permissões do usuário conectado.
Esta página detalha como gerenciar assinaturas de clientes para Flexible Sync. Para obter informações sobre a configuração de permissões para o Flexible Sync, consulte: Regras do Flexible Sync & Permissions (Permissões do Flexible Sync).
Gerencie assinaturas em seu aplicativo cliente
No aplicativo cliente, você adiciona, atualiza e remove assinaturas de queries específicas nos campos consultáveis. Isso determina quais dados são sincronizados com o dispositivo cliente.
Você pode:
Adicione assinaturas com um nome de assinatura opcional:
No Realm Swift SDK versão 10.43.0 e posterior, você pode usar o
.subscribe()
para assinar a queryResults
. Isso adiciona automaticamente a assinatura ao conjunto de assinaturas.Adicione manualmente uma assinatura ao conjunto de assinatura com a API do
subscriptions
. Use essa API se precisar de mais controle sobre as assinaturas por motivos de otimização de desempenho ou lógica de negócios. Consulte Considerações sobre desempenho para obter mais informações.
Reagir ao estado da assinatura
Atualizar assinaturas com novas queries
Remover assinaturas individuais ou todas as assinaturas de um tipo de objeto
Sobre os exemplos nesta página
Os exemplos nesta página usam um conjunto de dados simples para uma aplicação de lista de tarefas. Os dois tipos de objetos do Realm são Team
e Task
. Task
tem um taskName
, o nome do responsável e um sinalizador finalizado. Também há uma contagem dos minutos gastos trabalhando nele e uma data de vencimento. Um Team
tem teamName
, zero ou mais Tasks
, e uma lista de members
.
class Task: Object { true) var _id: ObjectId (primaryKey: var taskName: String var assignee: String? var completed: Bool var progressMinutes: Int var dueDate: Date } class Team: Object { true) var _id: ObjectId (primaryKey: var teamName: String var tasks: List<Task> var members: List<String> }
Os exemplos nesta página também assumem que você tem um usuário autorizado e uma configuração Flexible Sync:
let app = App(id: APPID) do { let credentials = emailPasswordCredentials(app: app) let user = try await app.login(credentials: credentials) var flexSyncConfig = user.flexibleSyncConfiguration() flexSyncConfig.objectTypes = [Task.self, Team.self] do { // Open the synced realm and manage Flexible Sync subscriptions } catch { print("Failed to open realm: \(error.localizedDescription)") // handle error } } catch { fatalError("Login failed: \(error.localizedDescription)") }
Inscrever-se para receber queries
Novidades na versão 10.43.0.
Para simplificar o gerenciamento de assinaturas, o Realm Swift SDK versão 10.43.0 adiciona APIs para assinar e cancelar a assinatura do conjunto de Results
de uma query. Essas APIs resumem os detalhes de adicionar e remover assinaturas manualmente.
Importante
A API do.subcribe() está em versão prévia
As APIs .subscribe()
e .unsubscribe()
descritas aqui estão atualmente na Pré-visualização. Essas APIs podem estar sujeitas a alterações futuras.
Inscrever-se em uma query
Com um usuário autenticado e uma configuração Flexible Sync, você pode abrir um realm sincronizado e uma query para os objetos que deseja ler e gravar. Você pode .subscribe() a essa query para criar uma assinatura Flexible Sync para objetos correspondentes à query:
let realm = try await Realm(configuration: flexSyncConfig) let results = try await realm.objects(Task.self) .where { $0.progressMinutes >= 60 }.subscribe() // Go on to work with subscribed results
Isso cria uma assinatura sem nome e a adiciona ao MutableSubscriptionSet
, semelhante à criação manual de uma assinatura.
Assinar uma query com um nome de assinatura
Se seu aplicativo funcionar com várias assinaturas ou se você quiser atualizar uma assinatura, talvez queira adicionar um nome ao assinar uma query.
Posteriormente, você poderá usar esse nome para atualizar a query de uma assinatura, verificar se há uma assinatura por nome ou remover a query por nome.
let realm = try await Realm(configuration: flexSyncConfig) let results = try await realm.objects(Team.self) .where { $0.teamName == "Developer Education" } .subscribe(name: "team_developer_education") // Go on to work with subscribed results
Aguarde uma assinatura de query para sincronizar
Quando você assina o conjunto Results
de uma query, esse conjunto não contém objetos até que seja sincronizado. Se o seu aplicativo criar objetos, talvez você não precise baixar os dados sincronizados antes de o usuário trabalhar com ele. No entanto, se seu aplicativo exigir dados do servidor antes que o usuário possa trabalhar com ele, você pode especificar que uma assinatura deve ser waitForSync
:
let realm = try await Realm(configuration: flexSyncConfig) let results = try await realm.objects(Team.self) .where { $0.members.contains("Bob Smith") } .subscribe( name: "bob_smith_teams", waitForSync: .onCreation) // After waiting for sync, the results set contains all the objects // that match the query - in our case, 1 print("The number of teams that have Bob Smith as a member is \(results.count)")
Esta opção utiliza o enum RLMWaitForSyncMode
, cujos casos são:
.onCreation: Espere para baixar objetos correspondentes quando seu aplicativo criar a assinatura. Caso contrário, volte sem aguardar novos downloads. O aplicativo deve ter uma conexão com a internet na primeira vez que você adicionar a assinatura.
.always: Espere para baixar objetos correspondentes quando
.subscribe()
for executado. O aplicativo deve ter uma conexão de internet quando o.subscribe()
for executado..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 abrir offline em inicializações subsequentes usando credenciais armazenadas em cache.
Opcionalmente, você pode especificar um valor timeout
do tipo TimeInterval.
Cancelar assinatura de uma query
Você pode cancelar a assinatura do conjunto Results
de uma consulta usando a API .unsubscribe() :
let realm = try await Realm(configuration: flexSyncConfig) let results = try await realm.objects(Task.self).where { $0.completed == false }.subscribe() // Go on to work with subscribed results. // Later... results.unsubscribe()
Isso remove a assinatura do MutableSubscriptionSet
, de forma semelhante à remoção manual de uma assinatura.
Um conjunto de Results
ainda pode conter objetos depois de chamar .unsubscribe()
se existir outra assinatura que contenha objetos sobrepostos.
Chamar .unsubscribe()
não espera que os objetos sejam removidos do domínio. Não há API para esperar que .unsubscribe()
sincronize com o servidor.
Assinar uma query confinada ao ator
Você pode se inscrever em uma query confinada ao ator no MainActor:
let realm = try await Realm(configuration: flexSyncConfig, actor: MainActor.shared) let results = try await realm.objects(Team.self) .where { $0.teamName == "Developer Education" } .subscribe(name: "team_developer_education") // Go on to work with subscribed results
Ou assine uma query sobre um ator personalizado:
let realm = try await Realm(configuration: flexSyncConfig, actor: CustomGlobalActor.shared) let results = try await realm.objects(Team.self) .where { $0.teamName == "Developer Education" } .subscribe(name: "team_developer_education") // Go on to work with subscribed results
Para obter mais informações sobre realms confinados a atores, consulte Use Realm with Actors - Swift SDK.
Gerenciar assinaturas manualmente
Você pode usar a API do subscriptions
para gerenciar manualmente um conjunto de assinaturas para queries específicas em campos de query.
Você pode:
Adicionar subscrições
Reagir ao estado da assinatura
Atualizar assinaturas com novas queries
Remover assinaturas individuais ou todas as assinaturas de um tipo de objeto
Os dados correspondentes à assinatura, onde o usuário tem as permissões apropriadas, sincronizam entre os dispositivos e o aplicativo de backend.
Você pode especificar um nome de string opcional para sua assinatura.
Quando você cria uma assinatura, o Realm procura dados correspondentes a uma query em um tipo de objeto específico. Você pode ter vários conjuntos de assinaturas em diferentes tipos de objetos. Você também pode ter várias queries no mesmo tipo de objeto.
Exemplo
Você pode criar uma assinatura com um nome explícito. Em seguida, você pode pesquisar essa assinatura por nome para atualizá-la ou removê-la.
QuerySubscription<Task>(name: "long-running-completed") { $0.completed == true && $0.progressMinutes > 120 }
Se você não especificar um name
para uma assinatura, você poderá pesquisar a assinatura pela string de query.
QuerySubscription<Team> { $0.teamName == "Developer Education" }
Observação
Subscrições duplicadas
Os nomes das assinaturas devem ser exclusivos. Tentando anexar uma assinatura com o mesmo nome de uma assinatura existente exibe um erro.
Se você não nomear explicitamente uma assinatura e, em vez disso, assinar a mesma query sem nome mais de uma vez, o Realm não persistirá queries duplicadas ao conjunto de assinaturas.
Se você assinar a mesma query mais de uma vez com nomes diferentes, a Realm manterá as duas assinaturas no conjunto de assinaturas.
Adicionar uma assinatura
Adicione uma assinatura em um bloco de atualização de assinaturas. Você anexa cada nova assinatura às assinaturas do Realm do cliente.
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
let realm = try await getRealmWithSingleSubscription() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmWithSingleSubscription() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.append( QuerySubscription<Team> { $0.teamName == "Developer Education" }) } return realm }
Você pode adicionar várias assinaturas dentro de um bloco de atualização de assinatura, incluindo assinaturas de diferentes tipos de objetos.
let realm = try await getRealmWithMultipleSubscriptions() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmWithMultipleSubscriptions() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.append( QuerySubscription<Task>(name: "completed-tasks") { $0.completed == true }) subscriptions.append( QuerySubscription<Team> { $0.teamName == "Developer Education" }) } return realm }
Bootstrap the Realm com assinaturas iniciais
Novidades na versão 10.28.0.
Você deve ter pelo menos uma assinatura antes de ler ou escrever no domínio. Você pode inicializar um realm com uma assinatura inicial definida ao abri-lo com o flexibleSyncConfiguration(). Passe o parâmetro initialSubscriptions
com as queries de assinatura que você deseja usar para embalar o domínio:
var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in subs.append( QuerySubscription<Team> { $0.teamName == "Developer Education" }) })
Se o seu aplicativo precisar executar novamente essa assinatura inicial toda vez que for iniciado, você poderá passar um parâmetro adicional - rerunOnOpen
. Este é um grupo que indica se a assinatura inicial deve ser executada novamente toda vez que o aplicativo iniciar. 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.
Neste exemplo, não queremos que os usuários sejam sobrecarregados por tarefas irrelevantes, portanto, carregaremos apenas as tarefas vencidas nos 7 dias anteriores e nos próximos 7 dias. Tarefas que deveriam ser cumpridas há mais de uma semana não são mais relevantes, e tarefas que devem sair mais do que a próxima semana também não são relevantes. Com rerunOnOpen
aqui, a query recalcula dinamicamente os objetos relevantes a serem sincronizados com base no intervalo de datas desejado sempre que o aplicativo é iniciado.
// Set the date a week ago and the date a week from now, as those are the dates we'll use // in the Flexible Sync query. `rerunOnOpen` lets the app recalculate this query every // time the app opens. let secondsInAWeek: TimeInterval = 604800 let dateLastWeek = (Date.now - secondsInAWeek) let dateNextWeek = (Date.now + secondsInAWeek) var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in subs.append( QuerySubscription<Task> { $0.dueDate > dateLastWeek && $0.dueDate < dateNextWeek }) }, rerunOnOpen: true)
Assinar todos os objetos de um tipo específico
Além de sincronizar todos os objetos que correspondem a uma determinada query, você pode se inscrever em todos os objetos de um tipo específico. Você faz isso anexando uma assinatura sem fornecer uma query.
Por exemplo, se você não quiser ver uma equipe específica, mas, em vez disso, quiser assinar todos os objetos Team
, poderá fazer o seguinte:
let realm = try await subscribeToObjectsOfAType() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func subscribeToObjectsOfAType() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.append(QuerySubscription<Team>(name: "all_teams")) } XCTAssertEqual(subscriptions.count, 1) // :remove return realm }
Verificar se há assinaturas existentes antes de adicionar uma assinatura
Se o fluxo do aplicativo anexar a mesma assinatura nomeada ao conjunto de assinaturas toda vez que você executar o aplicativo, isso não será permitido. Nesse caso, adicione uma verificação para uma assinatura existente antes de anexá-la:
let realm = try await checkAndAddSubscription() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func checkAndAddSubscription() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions let foundSubscription = subscriptions.first(named: "user_team") try await subscriptions.update { if foundSubscription != nil { foundSubscription!.updateQuery(toType: Team.self, where: { $0.teamName == "Developer Education" }) } else { subscriptions.append( QuerySubscription<Team>(name: "user_team") { $0.teamName == "Developer Education" }) } } return realm }
Aguarde as alterações na assinatura para sincronizar
Atualizar o conjunto de assinaturas localmente é apenas um componente da alteração de uma assinatura. Após a alteração da assinatura local, o território sincroniza com o servidor para resolver quaisquer atualizações nos dados devido à alteração da assinatura. Isso pode significar adicionar ou remover dados do domínio sincronizado.
Pre async/Aguardar
Se seu aplicativo não usa o recurso async/await do Swift, você pode reagir às alterações de assinatura sincronizando com o servidor usando o bloco onComplete
. Esse bloco é chamado depois que as assinaturas são sincronizadas com o servidor. Se você quiser reagir a alterações no estado da assinatura redesenhando uma interface do usuário, por exemplo, ou realizando outra ação com base nas alterações do conjunto de dados, realize essas ações em onComplete
. É aqui que você também pode lidar com erros opcionais que ocorrem durante a sincronização.
let subscriptions = realm.subscriptions subscriptions.update({ subscriptions.append( QuerySubscription<Task> { $0.assignee == "John Doe" }) }, onComplete: { error in // error is optional if error == nil { // Flexible Sync has updated data to match the subscription } else { // Handle the error } })
Async/Aguardar
Se seu aplicativo usa async/await, você não precisa do bloco onComplete
. A atualização é executada de forma assíncrona e exibe um erro se a atualização não puder ser concluída com sucesso.
func changeSubscription() async throws { let subscriptions = realm.subscriptions try await subcriptions.update { subscriptions.remove { QuerySubscription<Task> { $0.assignee == "Joe Doe" } } } }
Dica
Se a sua aplicação acessar Realm em um contexto do async/await
, marque o código com @MainActor
para evitar falhas relacionadas a threading.
Estado do conjunto de assinaturas
Use a propriedade SubscriptionSet.state para ler o estado atual do conjunto de assinaturas.
O estado superseded
é um SyncSubscriptionState que pode ocorrer quando outro tópico atualiza uma assinatura em uma instância diferente do conjunto de assinatura. Se o estado se tornar superseded
, você deverá obter uma nova instância do conjunto de assinaturas antes de poder atualizá-lo.
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.
Atualizar assinaturas com uma nova query
Você pode atualizar a query de uma assinatura usando updateQuery
. Neste exemplo, procuramos uma assinatura que corresponda à nossa query e a atualizamos com uma nova query.
let realm = try await getRealmWithUpdatedSubscriptions() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmWithUpdatedSubscriptions() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { if let foundSubscription = subscriptions.first(ofType: Team.self, where: { $0.teamName == "Developer Education" }) { foundSubscription.updateQuery(toType: Team.self, where: { $0.teamName == "Documentation" }) } } return realm }
Você também pode pesquisar uma assinatura pelo nome . Neste exemplo, pesquisamos uma query de assinatura por nome e a atualizamos com uma nova query.
let realm = try await getRealmWithUpdatedSubscriptionName() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmWithUpdatedSubscriptionName() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions let foundSubscription = subscriptions.first(named: "user-team") try await subscriptions.update { foundSubscription?.updateQuery(toType: Team.self, where: { $0.teamName == "Documentation" }) } return realm }
Remover subscrições
Para remover assinaturas, você pode:
Remover uma query de assinatura única
Remover todas as assinaturas de um tipo de objeto específico
Remover todas as assinaturas sem nome
Remover todas as assinaturas
Quando você remove uma query de assinatura, o Realm remove assíncronamente os dados sincronizados que corresponderam à query do dispositivo cliente.
Remover uma única assinatura
Você pode remover uma query de assinatura específica em um bloco de atualização de assinatura utilizando remove
. Especifique a query por nome ou use a query como uma string para localizar a query de assinatura apropriada para remover.
let realm = try await getRealmAfterRemovingSubscription() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmAfterRemovingSubscription() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions // Look for a specific subscription, and then remove it let foundSubscription = subscriptions.first(named: "docs-team") try await subscriptions.update { subscriptions.remove(foundSubscription!) } // Or remove a subscription that you know exists without querying for it try await subscriptions.update { subscriptions.remove(named: "existing-subscription") } return realm }
Remover todas as assinaturas de um tipo de objeto
Se quiser remover todas as assinaturas de um tipo de objeto específico, use o método removeAll
com ofType
em um bloco de atualização de assinatura.
let realm = try await getRealmAfterRemovingAllSubscriptionsToAnObjectType() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmAfterRemovingAllSubscriptionsToAnObjectType() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.removeAll(ofType: Team.self) } return realm }
Remover todas as assinaturas sem nome
Novidades na versão 10.43.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 não nomeadas do conjunto de assinaturas configurando unnamedOnly
para true
quando você chamar o método removeAll
:
let realm = try await Realm(configuration: flexSyncConfig) // Add 2 subscriptions, one named and one unnamed. let results = try await realm.objects(Team.self).where { $0.teamName == "Developer Education" }.subscribe(name: "team_developer_education") let results2 = try await realm.objects(Task.self).where { $0.completed == false }.subscribe() // Later, remove only the unnamed one let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.removeAll(unnamedOnly: true) }
Remover todas as assinaturas
Para remover todas as assinaturas do conjunto de assinaturas, use o método removeAll
em um bloco de atualização de assinatura.
Importante
Se você remover todas as assinaturas e não adicionar uma nova, receberá um erro. Um domínio aberto com uma configuração de Flexible Sync precisa de pelo menos uma assinatura para sincronizar com o servidor.
let realm = try await getRealmAfterRemovingAllSubscriptions() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func getRealmAfterRemovingAllSubscriptions() async throws -> Realm { let realm = try await Realm(configuration: flexSyncConfig) let subscriptions = realm.subscriptions try await subscriptions.update { subscriptions.removeAll() } return realm }
Considerações de desempenho
Eficiência da API
Adicionar 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. A cada .subscribe()
, o Swift SDK abre um novo bloco de atualização. Para obter melhor desempenho adicionando várias assinaturas, use a API subscriptions.update
descrita na seção Gerenciar assinaturas manualmente .
Atualizações de grupo para melhorar o desempenho
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.
Requisitos e limitações do Flexible Sync RQL
Requisitos de inscrição de campos de query indexados
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
==
ouIN
com uma constante pelo menos uma vez na query de inscrição. Por exemplo,user_id == $0, "641374b03725038381d2e1fb"
oustore_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 exemplostore_id IN {1,2,3} OR region=="Northeast"
é inválido porque usaOR
em vez deAND
. Da mesma forma,store_id == 1 AND active_promotions < 5 OR num_employees < 10
é inválido porque oAND
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
outruepredicate
são inválidos porque não contêm o campo de query indexado.
Operadores de consulta não suportados na sincronização flexível
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 |
|
Sufixos de query |
|
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.
Listar queries
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"
Objetos incorporados ou vinculados
A Flexible Sync não oferece suporte à consulta de propriedades em objetos ou links embarcados. Por exemplo, obj1.field == "foo"
.
Limite de tamanho da query
O limite de tamanho para qualquer assinatura de query em seu conjunto de assinatura é de 256 kB. Exceder esse limite resulta em um erro de LimitsExceeded.