Flexible Sync サブスクリプションの管理 - Swift SDK
項目一覧
- Overview
- サブスクリプション
- オブジェクト タイプへのサブスクライブ
- 権限
- クライアント アプリでのサブスクリプションの管理
- このページの例について
- クエリにサブスクライブ
- クエリにサブスクライブ
- サブスクリプション名付きのクエリにサブスクライブ
- クエリ サブスクリプションが同期するまで待機する
- クエリからのサブスクライブの解除
- アクター指定のクエリにサブスクライブ
- サブスクリプションの手動管理
- サブスクリプションを追加する
- サブスクリプションの変更が同期されるまで待機する
- サブスクリプション セットの状態
- 新しいクエリによるサブスクリプションの更新
- サブスクリプションの削除
- パフォーマンスに関する考慮事項
- API 効率
- パフォーマンス向上のためのグループ更新
- Flexible Sync RQL の要件と制限
- インデックス付きクエリ可能なフィールドのサブスクリプション要件
- Flexible Sync でサポートされていないクエリ演算子
- クエリをリストする
- 埋め込みオブジェクトまたはリンクされたオブジェクト
- クエリ サイズの制限
Overview
バージョン10.22.0の新機能。
Flexible Sync は、サブスクリプションと権限を使用して、アプリと同期するデータを決定します。
iOS クライアントで Flexible Sync を使用するには、次の手順に従います。
クライアント プロジェクトでユーザーを認証します。
サブスクリプションを手動で追加、アップデート、削除して、クライアントデバイスに同期するデータを決定できます。 Realm Swift SDK バージョン 10.43.0 以降では、サブスクリプションを手動で管理するだけでなく、 の代わりに クエリをサブスクライブできます。
Tip
Flexible Sync は 組み合わせ をサポートします。
サブスクリプション
バックエンドで Flexible Sync を構成するときは、クライアント アプリケーションがサブスクリプションを使用してクエリできるフィールドを指定します。
各サブスクリプションは、特定のオブジェクトタイプのクエリ可能なフィールドに対するクエリに対応します。 詳細については、App Services ドキュメントの「 クエリ可能なフィールド」を参照してください。
Realm はクエリ サブスクライブごとに、クエリに一致するデータを検索します。 ユーザーが適切な権限を持つサブスクリプションに一致するデータは、クライアントとバックエンド アプリケーション間で同期されます。
Realm Swift SDK クエリ エンジン を使用してクエリを構築できます。
オブジェクト タイプへのサブスクライブ
サブスクリプション セットはオブジェクトタイプに基づいています。 Realm オブジェクトのタイプが多い場合は、複数のサブスクリプションがあることがあります。 同じオブジェクトタイプに対して複数のサブスクライブを設定することもできます。
ただし、アプリ内で関係や非対称オブジェクトを使用する場合は、次の点に注意してください。
オブジェクト リンク
リンクされたオブジェクトを表示するには、オブジェクトとそのリンクされたオブジェクトの両方をサブスクリプション セットに追加する必要があります。
サブスクライブ結果に、結果に含まれていないオブジェクトにリンクする プロパティを持つオブジェクトが含まれている場合、リンクは nil に表示されます。 そのプロパティの値が正しく nil であるかどうか、また、リンク先のオブジェクトが存在してもクエリ サブスクリプションのビューの対象外であるかどうかを区別する方法はありません。
非対称オブジェクト
アプリがData Ingestを使用して非対称オブジェクトを一方向に同期する場合、それらのオブジェクトのサブスクリプションを作成することはできません。 アプリが同じレルムに非対称オブジェクトと非対称オブジェクトを含む場合は、非対称オブジェクトの Flexible Sync サブスクリプション クエリを追加できます。
権限
サブスクリプションは権限と並行して機能し、クライアント アプリケーションに同期するデータを決定します。 クライアント アプリケーションは、ログイン ユーザーの権限にも一致するサブスクリプションに一致するデータのサブセットのみを表示します。
このページでは、Flexible Sync のクライアント サブスクリプションを管理する方法について詳しく説明します。 Flexible Sync の権限の設定の詳細については、「 Flexible Sync のルールと権限 」を参照してください。
クライアント アプリでのサブスクリプションの管理
クライアント アプリケーションでは、クエリ可能なフィールドの特定のクエリへのサブスクリプションを追加、更新、および削除します。 これにより、クライアント デバイスに同期されるデータが決まります。
ユーザーは次のアクションを実行できます。
任意のサブスクリプション名でサブスクリプションを追加する。
Realm Swift SDK バージョン 10.43.0 以降では、
.subscribe()
を使用してクエリResults
をサブスクライブできます。 これにより、サブスクライブが サブスクリプション セット に自動的に追加されます。subscriptions
API を使用してサブスクリプションセットにサブスクライブを手動で追加します。 パフォーマンスの最適化やビジネス ロジック上の理由で、サブスクリプションをより詳細に制御する必要がある場合は、この API を使用します。 詳細については、 「パフォーマンスに関する考慮事項」 を参照してください。
Reactション状態に対応
新しいクエリでサブスクライブを更新する
オブジェクトタイプの個々のサブスクライブまたはすべてのサブスクライブを削除
このページの例について
このページの例では、タスク リスト アプリの単純なデータセットを使用しています。 2 つの Realm オブジェクトタイプはTeam
とTask
です。 Task
にはtaskName
、割り当て者の名前、完了したフラグがあります。 また、その作業に費やされた時間と期限もあります。 Team
にはteamName
、0 個以上のTasks
、および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> }
このページの例では、承認されたユーザーと 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)") }
クエリにサブスクライブ
バージョン 10.43.0 の新機能。
サブスクリプション管理を簡素化するために、Realm Swift SDK バージョン 10.43.0 では、クエリのResults
セットをサブスクライブおよびサブスクライブ解除するための API が追加されています。 これらの API では、サブスクリプションの手動追加と削除の詳細は抽象化されます。
重要
.subcribe() API はプレビュー段階
ここで説明されている.subscribe()
API と.unsubscribe()
API は現在プレビュー段階です。 これらの API は将来変更される可能性があります。
クエリにサブスクライブ
認証済みユーザーと Flexible Sync 構成を使用すると、同期された Realm を開き、読み取りや書込みを必要とするオブジェクトをクエリできます。 .subscribe() そのクエリに一致するオブジェクトの Flexible Sync サブスクリプションを作成します。
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
これにより、サブスクリプションを手動で作成するのと同様に、名前のないサブスクリプションが作成され、 MutableSubscriptionSet
に追加されます。
サブスクリプション名付きのクエリにサブスクライブ
アプリが複数のサブスクライブで動作する場合、またはサブスクリプションを更新する場合は、クエリをサブスクライブするときに名前を追加することをお勧めします。
この名前を使用して、後でサブスクライブのクエリを更新したり、名前を使用してサブスクライブを確認したり、名前を使用してクエリを削除したりできます。
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
クエリ サブスクリプションが同期するまで待機する
クエリのResults
セットをサブスクライブすると、そのセットは同期されるまでオブジェクトを含みません。 アプリが オブジェクトを作成する場合、ユーザーが同期データを操作する前に同期データをダウンロードする必要がない場合があります。 ただし、アプリでユーザーが操作する前にサーバーからのデータが必要な場合は、サブスクライブが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)")
このオプションではRLMWaitForSyncMode
列挙型が使用されます。そのケースは次のとおりです。
.onCreation: アプリがサブスクリプションを作成するときに、一致するオブジェクトをダウンロードするまで待機します。 それ以外の場合は、新しいダウンロードを待たずに戻ります。 サブスクリプションを初めて追加するときに、アプリはインターネット接続が必要です。
。常に:
.subscribe()
が実行されると、一致するオブジェクトをダウンロードするまで待機します。.subscribe()
を実行するとき、アプリはインターネットに接続する必要があります。.native: 一致するオブジェクトがダウンロードされるのを待たない アプリは、アプリが初めて起動するときにユーザーが認証するためにインターネット接続を必要としますが、キャッシュされた認証情報を使用して以降の起動ではオフラインで開くことができます。
オプションで、timeout
TimeInterval 型の 値を指定できます。
クエリからのサブスクライブの解除
.unsubscribe() メソッドを使用して、クエリのResults
セットからサブスクライブを解除できます API:
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()
これにより、サブスクライブを手動で削除するのと同様に、 MutableSubscriptionSet
からサブスクライブが削除されます。
重複するオブジェクトを含む別のサブスクリプションが存在する場合、 Results
セットには.unsubscribe()
を呼び出した後もオブジェクトが含まれることがあります。
.unsubscribe()
を呼び出しても、オブジェクトが Realm から削除されるのを待たなくなります。 .unsubscribe()
がサーバーと同期するまで待機する API はありません。
アクター指定のクエリにサブスクライブ
メインアクターで以下のようにアクター制限されたクエリをサブスクライブできます。
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
または、次のカスタム アクターでクエリをサブスクライブします。
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
アクター定義の Realm の詳細については、「 アクターでRealm を使用する - Swift SDK 」を参照してください。
サブスクリプションの手動管理
subscriptions
API を使用して、クエリ可能なフィールドの特定のクエリへのサブスクリプションのセットを手動で管理できます。
ユーザーは次のアクションを実行できます。
サブスクライブを追加する
Reactション状態に対応
新しいクエリでサブスクライブを更新する
オブジェクトタイプの個々のサブスクライブまたはすべてのサブスクライブを削除
ユーザーが適切な権限を持つサブスクリプションに一致するデータは、デバイスとバックエンド アプリケーション間で同期されます。
サブスクライブには任意の string 名を指定できます。
サブスクリプションを作成すると、Realm は特定のオブジェクトタイプに対するクエリに一致するデータを検索します。 異なるオブジェクトタイプに対して複数のサブスクリプションセットを持つことができます。 同じオブジェクトタイプに対して複数のクエリを設定することもできます。
例
明示的な名前のサブスクリプションを作成できます。 次に、そのサブスクリプションを名前で検索して更新または削除できます。
QuerySubscription<Task>(name: "long-running-completed") { $0.completed == true && $0.progressMinutes > 120 }
サブスクライブに name
を指定しない場合は、クエリstringでサブスクライブを検索できます。
QuerySubscription<Team> { $0.teamName == "Developer Education" }
注意
重複したサブスクライブ
サブスクリプション名は一意である必要があります。 既存のサブスクリプションと同じ名前のサブスクリプションを追加しようとすると、エラーがスローされます。
サブスクリプションを明示的に名前付けせず、代わりに同じ名前のないクエリを複数回サブスクライブする場合、Realm はサブスクライブセットへのクエリを重複させません。
異なる名前で同じクエリを複数回サブスクライブする場合、Realm は両方のサブスクライブをサブスクリプションセットに永続化します。
サブスクリプションを追加する
サブスクリプション更新ブロックにサブスクライブを追加します。 新しいサブスクリプションはそれぞれ、クライアントの Realm サブスクリプションに追加します。
Tip
アプリがasync/await
コンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActor
でマークします。
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 }
さまざまなオブジェクトタイプのサブスクライブを含む、サブスクリプション更新ブロック内に複数のサブスクリプションを追加できます。
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 }
初期サブスクリプションで Realm をブートストラップする
バージョン10.28.0の新機能。
Realm から読み取りまたは書込み (write) する前に、少なくとも 1 つのサブスクリプションが必要です。 FlexibleSyncConfiguration()を使用してRealmを開くと、初期サブスクリプションセットでRealmをブートストラップすることができます。 Realm のブートストラップに使用するサブスクリプション クエリを含むinitialSubscriptions
パラメーターを渡します。
var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in subs.append( QuerySubscription<Team> { $0.teamName == "Developer Education" }) })
アプリを起動するたびにアプリがこの初期サブスクリプションを再実行する必要がある場合は、追加のパラメータ - rerunOnOpen
を渡すことができます。 これは、アプリを起動するたびに初期サブスクリプションを再実行するかどうかを示すブール値です。 動的時間範囲やサブスクライブの静的変数の再計算が必要なその他のクエリを再実行するには、この操作が必要になる場合があります。
この例では、ユーザーが無関係なタスクに選択されることを避け、過去 7 日以内と次の 7 日以内に期限切れのタスクのみをロードします。 1 週間以上前に期限が切れたタスクは関連性がなくなり、次の週より期限が切れたタスクも関連性がなくなります。 ここでrerunOnOpen
を使用すると、アプリを起動するたびに、クエリは目的のデータ範囲に基づいて同期する関連オブジェクトを動的に再計算します。
// 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)
特定の型のすべてのオブジェクトへのサブスクライブ
特定のクエリに一致するすべてのオブジェクトを同期するだけでなく、特定のタイプのすべてのオブジェクトをサブスクライブできます。 クエリを提供せずにサブスクリプションを追加することで、これを実現します。
たとえば、特定のチームは表示されたくないが、すべてのTeam
オブジェクトにサブスクライブしたい場合は、次のようにします。
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 }
サブスクリプションを追加する前に既存のサブスクリプションを確認する
アプリケーションを実行するたびにアプリケーション フローが同じ名前のサブスクリプションをサブスクリプションセットに追加する場合、これは許可されていません。 この場合は、既存のサブスクリプションを追加する前に、そのサブスクリプションのチェックを追加します。
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 }
サブスクリプションの変更が同期されるまで待機する
サブスクリプションセットをローカルに更新することは、サブスクリプション変更の 1 つの要素のみです。 ローカル サブスクリプションの変更後、Realm はサーバーと同期して、サブスクリプションの変更によるデータの更新を解決します。 これは、同期された Realm からデータを追加または削除することを意味します。
Pre Async/Await
アプリケーションが Swift の async/ React機能を使用していない場合、onComplete
ブロックを使用してサーバーと同期するサブスクリプションの変更に対応できます。 このブロックは、サブスクライブがサーバーと同期された後に呼び出されます。 UI を再レンダリングしたり、データセットの変更に基づいて別のアクションを実行したりして、 Reactライブ状態の変更に対応する場合は、onComplete
でそれらのアクションを実行します。 また、同期中に発生する任意のエラーを処理できる場所でもあります。
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/Await
アプリケーションで async/await が使用される場合、 onComplete
ブロックは必要ありません。 更新は非同期で実行され、更新が正常に完了できない場合はエラーがスローされます。
func changeSubscription() async throws { let subscriptions = realm.subscriptions try await subcriptions.update { subscriptions.remove { QuerySubscription<Task> { $0.assignee == "Joe Doe" } } } }
Tip
アプリがasync/await
コンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActor
でマークします。
サブスクリプション セットの状態
サブスクリプションセットの現在の状態を読み取るには、 SubscriptionSet.rateプロパティを使用します。
superseded
状態はSyncSubscriptionStateであり、サブスクリプションセットの別のインスタンスで別のスレッドがサブスクリプションを更新するときに発生する可能性があります。 状態がsuperseded
になった場合は、更新する前にサブスクライブ セットの新しいインスタンスを取得する必要があります。
注意
サブスクリプション状態「完了」
サブスクリプションセットの状態「完了」は、「同期が実行された」または「すべてのドキュメントが同期された」を意味するものではありません。 「完了」とは、次の 2 つの処理が発生したことを意味します。
サブスクライブは、現在サーバーと同期されているアクティブなサブスクリプションセットになりました。
サブスクリプションがサーバーに送信されたときにサブスクリプションに一致したドキュメントは、現在、ローカルデバイス上にあります。 これには、現在サブスクリプションに一致しているすべてのドキュメントが必ずしも含まれるわけではないことに注意してください。
Realm SDK には、サブスクリプションに一致するすべてのドキュメントがデバイスに同期されているかどうかを確認する方法は提供されていません。
新しいクエリによるサブスクリプションの更新
updateQuery
を使用してサブスクライブのクエリを更新できます。 この例では、クエリに一致するサブスクライブを検索し、新しいクエリで更新します。
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 }
という名前でサブスクライブを検索することもできます。 この例では、サブスクライブ クエリを名前で検索し、新しいクエリで更新します。
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 }
サブスクリプションの削除
サブスクリプションを削除するには、次の方法があります。
1 つのサブスクライブ クエリを削除
特定のオブジェクトタイプへのすべてのサブスクライブを削除
名前のないサブスクライブをすべて削除します
すべてのサブスクライブを削除
サブスクリプション クエリを削除すると、Realm はクライアント デバイスからクエリに一致した同期データを非同期に削除します。
1 つのサブスクリプションを削除
remove
を使用して、サブスクライブ更新ブロック内の特定のサブスクライブ クエリを削除できます。 削除する適切なサブスクライブ クエリを見つけるには、クエリを名前で指定するか、クエリを string として使用します。
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 }
オブジェクト タイプへのすべてのサブスクリプションを削除
特定のオブジェクトタイプへのすべてのサブスクライブを削除する場合は、サブスクライブ更新ブロックでofType
とともにremoveAll
メソッドを使用します。
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 }
すべての名前のないサブスクリプションを削除
バージョン 10.43.0 の新機能。
一時的な、または動的に生成される名前のないサブスクリプションは削除するが、名前付きサブスクリプションはその場で残すしたい場合があります。
次のように、 removeAll
メソッドを呼び出すときにunnamedOnly
をtrue
に設定することで、サブスクリプションセットから名前のないすべてのサブスクライブを削除できます。
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) }
すべてのサブスクリプションを削除
サブスクリプションセットからすべてのサブスクライブを削除するには、サブスクライブ更新ブロックでremoveAll
メソッドを使用します。
重要
すべてのサブスクライブを削除し、新しいサブスクライブを追加しないと、 エラーが発生します。 柔軟な同期構成で開かれたRealmでは、サーバーと同期するために少なくとも 1 つのサブスクライブが必要です。
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 }
パフォーマンスに関する考慮事項
API 効率
「クエリへのサブスクライブ」セクションで説明されている.subscribe()
と.unsubscribe()
API を使用して複数のサブスクリプションを追加する場合、サブスクリプションを手動で管理する場合にバッチ更新を実行するより効率が低くなります。 .subscribe()
ごとに、Swift SDK は新しい更新ブロックを開きます。 複数のサブスクリプションを追加する際のパフォーマンスを向上させるには、「サブスクリプションの手動管理」セクションで説明されているsubscriptions.update
API を使用します。
パフォーマンス向上のためのグループ更新
サブスクリプションセットのすべての書込みトランザクション (write transaction) にはパフォーマンス コストがかかります。 セッション中に Realm オブジェクトを複数更新する必要がある場合は、すべての変更が完了するまで編集されたオブジェクトをメモリ内に保持することを検討してください。 これにより、すべての変更ではなく、完全で更新されたオブジェクトのみが Realm に書き込まれるため、同期のパフォーマンスが向上します。
Flexible Sync RQL の要件と制限
インデックス付きクエリ可能なフィールドのサブスクリプション要件
インデックス付きのクエリ可能なフィールドをアプリに追加すると、厳密にパーティション化されたデータに対する単純なクエリのパフォーマンスが向上します。 たとえば、クエリがデバイス、ストア、またはユーザーにデータを厳密にマッピングするアプリuser_id == $0, “641374b03725038381d2e1fb”
など)は、インデックス付きクエリ可能なフィールドの候補となります。 ただし、インデックス付きのクエリ可能なフィールドには、クエリ サブスクリプションで使用するための特定の要件があります。
インデックス付きクエリ可能なフィールドは、すべてのサブスクライブ クエリで使用する必要があります。 クエリから欠落することはできません。
インデックス付きクエリ可能なフィールドは、サブスクライブ クエリで少なくとも 1 回、定数に対して
==
またはIN
の比較を使用する必要があります。 たとえば、user_id == $0, "641374b03725038381d2e1fb"
やstore_id IN $0, {1,2,3}
などです。
オプションとして、インデックス付きクエリ可能なフィールドが==
またはIN
を少なくとも 1 回使用して定数と直接比較される限り、 AND
比較を含めることができます。 たとえば、 store_id IN {1,2,3} AND region=="Northeast"
やstore_id == 1 AND (active_promotions < 5 OR num_employees < 10)
などです。
インデックス付きクエリ可能なフィールドに対する無効なFlexible Sync クエリには、次のクエリが含まれます。
インデックス付きクエリ可能なフィールドは、クエリの残りの部分で
AND
を使用しません。store_id IN {1,2,3} OR region=="Northeast"
OR
たとえば、AND
は ではなく を使用しているため無効です。同様に、store_id == 1 AND active_promotions < 5 OR num_employees < 10
は無効です。AND
はクエリ全体ではなく、その横にあるタームにのみ適用されるためです。インデックス付きクエリ可能なフィールドは 等価演算子 では使用されません。 たとえば、
store_id > 2 AND region=="Northeast"
は無効です。インデックス付きクエリ可能なフィールドでは>
演算子のみが使用され、等価比較がないためです。クエリに、インデックス付きのクエリ可能なフィールドが完全にありません。 たとえば、
region=="Northeast
またはtruepredicate
は、インデックス付きクエリ可能なフィールドが含まれていないため無効です。
Flexible Sync でサポートされていないクエリ演算子
RQL 演算子を使用する場合、Flexible Sync にはいくつかの制限があります。 同期するデータを決定するクエリ サブスクリプションを書込む場合、サーバーはこれらのクエリ演算子をサポートしていません。 ただし、RQL 機能の全範囲を使用して、クライアント アプリケーション内の同期されたデータセットをクエリすることはできます。
演算子タイプ | サポートされていない演算子 |
---|---|
集計演算子 | @avg , @count , @max , @min , @sum |
クエリサフィックス | DISTINCT , SORT , LIMIT |
大文字と小文字を区別しないクエリ( [c]
)は、インデックスを効果的に使用できません。 その結果、大文字と小文字を区別しないクエリはパフォーマンスの問題を引き起こす可能性があるため、推奨されません。
Flexible Sync は、配列フィールドの@count
のみをサポートします。
クエリをリストする
Flexible Sync は、 IN
演算子を使用するクエリ リストをサポートしています。
定数のリストをクエリして、クエリ可能なフィールドの値が含まれているかどうかを確認できます。
// Query a constant list for a queryable field value "priority IN { 1, 2, 3 }"
クエリ可能なフィールドに配列値がある場合は、定数値が含まれているかどうかをクエリできます。
// Query an array-valued queryable field for a constant value "'comedy' IN genres"
警告
Flexible Sync クエリでは、2 つのリストを相互に比較することはできません。 RQLこれは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"
埋め込みオブジェクトまたはリンクされたオブジェクト
Flexible Sync は、 埋め込みオブジェクトまたはリンク のプロパティに対するクエリをサポートしていません。 たとえば、 obj1.field == "foo"
。
クエリ サイズの制限
サブスクリプションセット内の特定のクエリ サブスクライブのサイズ制限は256 kBです。 この制限を超えると、 LimitsExceeded エラー が発生します。