関係 - Kotlin SDK
このページでは、データモデル内のオブジェクト間の関係を定義する方法について説明します。 Realm オブジェクトとその定義方法については、「 Realm オブジェクトモデルの定義 - Kotlin SDK 」を参照してください。
リレーショナルデータベースとは異なり、Realm は関係を定義するためにブリッジ テーブルや明示的な結合を使用することはありません。 代わりに、Realm は埋め込みオブジェクトまたは他の Realm オブジェクトへの参照プロパティを介して関係を処理します。 これらのプロパティから直接読み取りと書込みを行います。 そのため、クエリ関係は、他のプロパティに対するクエリと同等のパフォーマンスが得られます。
関係タイプ
Realm オブジェクト間の関係には、次の 2 つのプライマリ タイプがあります。
対 1 の関係
対多の関係
Realm は、同じ Realm 内の他のオブジェクトからのオブジェクト参照を本質的に制限しません。 つまり、Realm の関係は暗黙的に「多対多」または「多対多」です。 関係を「多から 1/多から多」ではなく、「1 と 1 から多」に関係を制限する唯一の方法は、親が 1 つだけのネストされたオブジェクトである埋め込みオブジェクトを使用することです。
関係を定義する
別の Realm オブジェクトを参照するオブジェクト プロパティを定義することで、オブジェクト スキーマで関係を定義できます。 Realm オブジェクトをプロパティとして使用する方法の詳細。
次のタイプを使用して関係を定義できます。
RealmObject
RealmList <? extends RealmObject>
RealmSet <? extends RealmObject>
また、ある Realm オブジェクトを別の Realm オブジェクトに直接埋め込み、 EmbeddedRealmObject
タイプのネストされたデータ構造を作成することもできます。 ただし、埋め込みオブジェクトには追加の制約があります。 詳細については、「 埋め込みオブジェクトの定義」セクションを参照してください。
To-1 の関係プロパティの定義
対 1 の関係は、1 つのプロパティをRealmObject
オブジェクトタイプの単一のインスタンスにマッピングします。 複数の親オブジェクト インスタンスが同じ子インスタンスを参照することを妨げるものではありません。 厳密な 1 対 1 の関係を強制する場合は、代わりに埋め込みオブジェクトを使用します。
注意
対 1 の関係フィールドをnull
に設定すると、オブジェクト間の接続が削除されますが、Realm は参照されたオブジェクトを削除しません。 親オブジェクトが削除されたときに参照されたオブジェクトを削除する場合は、代わりに埋め込みオブジェクトを使用します。
オブジェクト間の 1 対 1 の関係を定義するには、データモデルで定義されたRealmObject
オブジェクトであるタイプの任意のオブジェクト プロパティを定義します。 これは、異なる Realm オブジェクトタイプまたは同じ Realm オブジェクトタイプにすることができます。
// Relationships of Realm objects must be of RealmObject type class Frog : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" var age: Int = 0 // Property of RealmObject type (MUST be null) var favoritePond: Pond? = null var bestFriend: Frog? = null }
ToMany 関係プロパティの定義
対多の関係は、1 つのプロパティをRealmObject
オブジェクトタイプの 0 つ以上のインスタンスにマッピングします。 複数の親オブジェクト インスタンスが同じ子インスタンスを参照することを妨げるものではありません。 厳密な 1 対多の関係を強制する場合は、代わりに埋め込みオブジェクトを使用します。
Realm では、対多の関係は Realm オブジェクトのコレクション( RealmListまたはRealmSet )です。 オブジェクトモデルでコレクションを定義する方法の詳細については、「コレクションのプロパティの定義 」を参照してください。
オブジェクト間の対多の関係を定義するには、タイプがRealmList<E>
またはRealmSet<E>
であるオブジェクト プロパティを定義します。ここでは、 <E>
はデータモデルで定義されたRealmObject
オブジェクトタイプです。 これは、異なる Realm オブジェクトタイプまたは同じ Realm オブジェクトタイプにすることができます。
// Relationships of RealmList<E> or RealmSet<E> must be of RealmObject type class Forest : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // Set of RealmObject type (CANNOT be null) var frogsThatLiveHere: RealmSet<Frog> = realmSetOf() // List of RealmObject type (CANNOT be null) var nearbyPonds: RealmList<Pond> = realmListOf() }
逆の関係の定義
逆の関係とは、子RealmObject
オブジェクトとそれを参照する他の親オブジェクトとの間の自動バックリンクの関係です。 逆の関係は、多対 1 または多対多の関係で子オブジェクトにリンクすることができます。 厳密な 1 対 1 または 1 対多の逆関係を強制する場合は、代わりに埋め込みオブジェクトを使用します。
関係の定義は一方向であるため、オブジェクトのモデルでプロパティを逆の関係として明示的に定義する必要があります。 たとえば、「ユーザーが多数の投稿を持っている」という対多の関係では、「書き込みはユーザーに属する」の関係が自動的に作成されることはありません。 ただし、書き込みの所有者を示す ユーザー プロパティを書き込みに追加することはできます。 これにより、書き込みが属するユーザーを検索するために別のクエリを実行する代わりに、書き込みからユーザーへの逆の関係でクエリを実行できます。 関係は多対 1 または多対多であるため、逆の関係にすると、ゼロ、1、または多のオブジェクトが生成されます。
注意
Realm は、指定された関係からオブジェクトが追加または削除されるたびに、暗黙的な関係を自動的に更新します。 バックリンク コレクションからアイテムを手動で追加または削除することはできません。
オブジェクト間の逆関係を定義するには、まず親オブジェクトで、タイプがRealmList<E>
、 RealmSet<E>
、またはRealmDictionary<E>
であるコレクション プロパティを定義します<E>
は、データモデルで定義されたRealmObject
オブジェクトタイプです) 。 これは、異なる Realm オブジェクトタイプまたは同じ Realm オブジェクトタイプにすることができます。
// Parent object must have RealmList<E>, RealmSet<E>, or // RealmDictionary<K,V> property of child type class User : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // List of child RealmObject type (CANNOT be nullable) var posts: RealmList<Post> = realmListOf() // Set of child RealmObject type (CANNOT be nullable) var favoritePosts: RealmSet<Post> = realmSetOf() // Dictionary of child RealmObject type (value MUST be nullable) var postByYear: RealmDictionary<Post?> = realmDictionaryOf() }
次に、 RealmResults<E>
の子オブジェクトに不変のバックリンクプロパティを定義します。ここでは、 <E>
は親オブジェクトタイプです。
// Backlink of RealmObject must be RealmResults<E> of parent object type class Post : RealmObject { var title: String = "" var date: RealmInstant = RealmInstant.now() // Backlink to parent RealmObject type (CANNOT be null & MUST be val) val user: RealmResults<User> by backlinks(User::posts) }
埋め込みオブジェクトの定義
埋め込みオブジェクトは、単一の特定の親オブジェクトの内部にデータをネストするために使用できる特殊なタイプの Realm オブジェクトです。 埋め込みオブジェクトは、前のセクションで説明された関係と同様の 1 対 1、1 対多、または逆の関係にすることができますが、関係は単一の親オブジェクトとEmbeddedRealmObject
の間の 1 対の関係に制限されます。 型。
埋め込みオブジェクトは独立した Realm オブジェクトとして存在できないため、考慮する必要がある追加の制約があります。
埋め込みオブジェクトは親による厳密な所有権があります。 親オブジェクト間で埋め込みオブジェクトを共有することはできません。
埋め込みオブジェクトは、親のライフサイクルを継承します。 たとえば、親オブジェクトを削除すると、埋め込みオブジェクトも削除されます。
埋め込みオブジェクトは、明確な包含または所有権関係がある場合に便利です。 たとえば、 Address
オブジェクトはUser
オブジェクトに埋め込まれます。これは、ユーザーのコンテキスト内のアプリケーションでのみ意味があるためです。
Tip
埋め込みオブジェクトタイプは再利用可能で構成可能です
複数の親オブジェクトタイプと他の埋め込みオブジェクトタイプ内で、同じ埋め込みオブジェクトタイプを使用できます。
1 対 1 の関係
親と 1 対 1 の関係を持つ埋め込みオブジェクトを定義するには、データモデルですでに定義されているタイプのEmbeddedRealmObject
であるオブジェクト プロパティを定義します。
// To-one embedded relationships must be of EmbeddedRealmObject type class Contact : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // Property of EmbeddedRealmObject type (MUST be null) var address: EmbeddedAddress? = null } class EmbeddedAddress : EmbeddedRealmObject { var propertyOwner: Contact? = null var street: String? = "" // Embed another EmbeddedRealmObject type var country: EmbeddedCountry? = null } class EmbeddedCountry : EmbeddedRealmObject { var name: String = "" }
1 対多の関係
親との 1 対多の埋め込み関係を持つ埋め込みオブジェクトを定義するには、タイプがRealmList<E>
であるオブジェクト プロパティを定義します。ここでは、 <E>
はデータモデルで定義されたEmbeddedRealmObject
オブジェクトタイプです。
// To-many embedded relationships must be a RealmList<E> or // RealmDictionary<K, V> property of EmbeddedRealmObject type class Business : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // List of EmbeddedRealmObject type (CANNOT be null) var addresses: RealmList<EmbeddedAddress> = realmListOf() // Dictionary of EmbeddedRealmObject type (value MUST be nullable) var addressByYear: RealmDictionary<EmbeddedAddress?> = realmDictionaryOf() }
RealmSet<E>
は埋め込みオブジェクトをサポートしていないため、 RealmSet<E>
タイプで埋め込みオブジェクトを定義することはできません。
逆の関係
親と逆の関係を持つ埋め込みオブジェクトを定義するには、まず親オブジェクト内でタイプがRealmList<E>
またはRealmDictionary<E>
であるコレクション プロパティを定義します。ここでは、 <E>
はデータモデルで定義されたEmbeddedRealmObject
オブジェクトタイプです。 :
// Parent object must have RealmList<E> or RealmDictionary<K, V> // property of child EmbeddedRealmObject type class User : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // List of child EmbeddedRealmObject type (CANNOT be nullable) var posts: RealmList<Post> = realmListOf() // Dictionary of child EmbeddedRealmObject type (value MUST be nullable) var postByYear: RealmDictionary<Post?> = realmDictionaryOf() }
RealmSet<E>
は埋め込みオブジェクトをサポートしていないため、 RealmSet<E>
タイプで埋め込みオブジェクトを定義することはできません。
次に、親オブジェクトタイプであるタイプを持つ子オブジェクトに、不変のバックリンクプロパティを定義します。
// Backlink of EmbeddedRealmObject must be parent object type class Post : EmbeddedRealmObject { var title: String = "" var date: RealmInstant = RealmInstant.now() // Backlink to parent RealmObject type (CANNOT be null & MUST be val) val user: User by backlinks(User::posts) }