Docs Menu
Docs Home
/ /
Atlas Device SDK
/ / /

Realm オブジェクトの更新 - Kotlin SDK

項目一覧

  • アップデート操作
  • 既存のオブジェクトの更新
  • Realm オブジェクトの更新
  • 埋め込みオブジェクトの更新
  • 複数のオブジェクトの更新
  • Realm プロパティの更新
  • MutableRealmInt(counter)プロパティを更新
  • RealmAny(混合)プロパティの更新
  • コレクション プロパティを更新
  • RealmList の更新
  • RealmSet の更新
  • 辞書の更新
  • 関係の更新
  • To1 の関係の更新
  • ToMany 関係の更新
  • 逆の関係の更新
  • Realm オブジェクトのアップサート

このページでは、 Kotlin SDK を使用してローカルまたは同期された Realm 内の既存の Realm オブジェクトを更新する方法について説明します。 Realm でオブジェクトを作成する方法の詳細については、「 Realm オブジェクトの作成 - Kotlin SDK 」を参照してください。

Realm は、Realm オブジェクトと埋め込みオブジェクトに対するアップデートとアップサート操作をサポートしています。 アップサート操作では、オブジェクトの新しいインスタンスが挿入されるか、特定の条件を満たす既存のオブジェクトが更新されます。 詳細については、このページの [ Realm オブジェクトのアップサート ]セクションを参照してください。

非対称オブジェクトは更新できません。 これは、非対称オブジェクトが Realm に永続しない特殊な書込み専用オブジェクトであるためです。 For information on how to use asymmetric objects in your application, refer to Stream Data to Atlas - Kotlin SDK.

注意

同期された Realm への書き込み

Realm 内のオブジェクトを更新する構文は、ローカル Realm または同期された Realm で同じです。 ただし、同期された Realm での書込み (write) 操作が成功するかどうかを判断する追加の考慮事項があります。 詳細については、「 同期された Realm へのデータの書き込み - Kotlin SDK 」を参照してください。

アップデート操作やアップサート操作を含め、Realm を変更するすべての操作は、書込みトランザクション内で実行する必要があります。 書込みトランザクションは、Realm のwrite () メソッドまたはwriteBlocking()メソッドに渡されます。 このコールバック内でMutableRealmインスタンスにアクセスし、Realm 内のオブジェクトを更新できます。 書込みトランザクションと Realm がそれを処理する方法の詳細については、「 書込みトランザクション 」を参照してください

さらに、書込みトランザクション内でのみアクセスできるライブ オブジェクトのみを変更できます。 MutableRealm.findLarge() を使用してトランザクション内で固定されたオブジェクトを実行中のオブジェクトに変換できます。

変更する前に凍結されたオブジェクトを変換する

val frozenFrog = realm.query<Frog>().find().first()
// Open a write transaction
realm.write {
// Get the live frog object with findLatest(), then update it
findLatest(frozenFrog)?.let { liveFrog ->
liveFrog.name = "Kermit"
liveFrog.age -= 1
}
}

Realm 内に保存されている Realm オブジェクトまたは埋め込みオブジェクトのプロパティを変更するには、次の手順に従います。

  1. Realm.write()を使用して書込みトランザクションを開きます またはRealm.writeBlocking() の

  2. query()を使用して、変更するオブジェクトをトランザクションの可変邦土をクエリして、ライブ オブジェクトを取得します。

    1. query()に渡される型パラメータとしてオブジェクトタイプを指定します。

    2. (任意)クエリを指定して、返されたオブジェクトのセットをフィルタリングします。 クエリフィルターを含めない場合、指定された型のすべてのオブジェクトが返されます。 Kotlin SDK を使用したクエリの詳細については、「 Realm オブジェクトの読み取り - Kotlin SDK 」を参照してください。

    重要

    オブジェクトはライブでなければなりません

    変更できるのは、ライブ オブジェクトのみです。 クエリが書込みトランザクションの外部で発生する場合は、 mutableRealm.findLatest()を使用してトランザクション内で固定オブジェクトをライブ オブジェクトに変換する必要があります。

  3. 書込みトランザクション ( 書込みトランザクション (write transaction)内でオブジェクトを変更します。 適用ブロック を使用できます 複数のプロパティを一度に構成します。 Realmが書込みトランザクション (write transaction) をコミットすると、すべての変更は自動的に邦土に永続化されます。

注意

String またはバイト配列の更新

Realm はフィールド全体を操作するため、文字列またはバイト配列の個々の要素を直接更新することはできません。 代わりに、フィールド全体を読み取り、個々の要素に変更を加えてから、フィールド全体をトランザクション ブロックで再度書き戻す必要があります。

Realm オブジェクトを更新するには、更新対象の特定のオブジェクトを返すフィルターを使用して タイプのクエリを実行します。 次に、オブジェクトのプロパティを変更します。

Tip

一意の識別情報の使用

クエリが正しいオブジェクトを返すように、プライマリキー 値などの一意の識別情報でフィルタリングすることをお勧めします。

次の例では、プライマリキーでFrogオブジェクトをクエリし、 nameageプロパティを更新します。

// Query and update a realm object in a single write transaction
realm.write {
val liveFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
liveFrog.name = "Michigan J. Frog"
liveFrog.age += 1
}

埋め込みオブジェクトは、個々のプロパティを変更するか、埋め込みオブジェクト全体を上書きすることで更新できます。

Tip

ドット表記で埋め込みオブジェクトにアクセス

ドット表記 を使用して、通常のネストされたオブジェクトと同様に埋め込みオブジェクトのプロパティにアクセスできます。 詳細については、 「 埋め込みオブジェクト プロパティでフィルタリング 」を参照してください。

埋め込みオブジェクト内の 1 つ以上のプロパティを更新するには、親オブジェクトまたは埋め込みオブジェクトを取得し、書込みトランザクション (write transaction) で埋め込みオブジェクトのプロパティを再割り当てします。

次の例では、埋め込みEmbeddedAddressオブジェクトを含むContactオブジェクトがあります。 埋め込みオブジェクトのプロパティをいくつかの操作でアップデートします。

// Modify embedded object properties in a write transaction
realm.write {
// Fetch the objects
val addressToUpdate = findLatest(address) ?: error("Cannot find latest version of embedded object")
val contactToUpdate = findLatest(contact) ?: error("Cannot find latest version of parent object")
// Update a single embedded object property directly
addressToUpdate.street = "100 10th St N"
// Update multiple properties
addressToUpdate.apply {
street = "202 Coconut Court"
city = "Los Angeles"
state = "CA"
postalCode = "90210"
}
// Update property through the parent object
contactToUpdate.address?.state = "NY"
}

埋め込みオブジェクトを完全に上書きするには、書込みトランザクション(write transaction)で新しい埋め込みオブジェクトのインスタンスを親プロパティに割り当てます。 これにより、既存の埋め込みオブジェクトが削除されます。

次の例では、埋め込みEmbeddedAddressオブジェクトを含むContactオブジェクトがあります。 新しいEmbeddedAddressオブジェクトを定義し、それを親プロパティに割り当てます。

realm.write {
val parentObject = query<Contact>("_id == $0", PRIMARY_KEY_VALUE).find().first()
val newAddress = EmbeddedAddress().apply {
propertyOwner = Contact().apply { name = "Michigan J. Frog" }
street = "456 Lily Pad Ln"
country = EmbeddedCountry().apply { name = "Canada" }
}
// Overwrite the embedded object with the new instance (deletes the existing object)
parentObject.address = newAddress
}

Realm 内の複数のオブジェクトを更新することもできます。

  1. Realm.query() を使用して、オブジェクトのコレクションの Realm をクエリします。

  2. Realm.write()を使用して書込みトランザクションを開きます またはRealm.writeBlocking() の

  3. クエリによって返されたRealmResultのセットの要素を更新します。

val tadpoles = realm.query<Frog>("age <= $0", 2)
for (tadpole in tadpoles.find()) {
realm.write {
findLatest(tadpole)?.name = tadpole.name + " Jr."
}
}

オブジェクトタイプの定義方法によっては、 Realm 固有の特別なタイプであるプロパティがある場合があります。

次の Realm API 関数を使用して、 MutableRealmIntプロパティ値を更新できます。

  • increment()

  • decrement()

  • set()

これらのメソッドは、ミューテーションされた値を持つMutableRealmIntプロパティを返します。

Tip

set() 演算子の使用に注意が必要

set()演算子は、 increment()またはdecrement()への以前の呼び出しを上書きします。 ユースケースでファジーカウントが受け入れられない限り、 set()increment()またはdecrement()と混在させることは推奨されません。

Realm API 関数に加えて、 Kotlin の標準ライブラリ が提供するものと同様の、次の演算子とインデックス関数のセットも使用できますLong の場合 :

  • 非接頭辞演算子: unaryPlusunaryMinus

  • インクリメント演算子とデクリメント演算子: incdecincrementdecrementと混同しないでください)

  • 算術演算子: plusminustimesdivrem

  • 等価演算子: equals

  • 比較演算子: compareTo

  • Bitwise functions: shl, shr, ushr, and, or, xor, inv

ただし、これらの演算子とインデックス関数は、それが呼び出されるインスタンスをミューテーションしません。 代わりに、操作の結果を持つ新しい非マネージド インスタンスが返されます。

重要

Realm メソッドのみがミューテーションされた値を生成します

ミューテーションされた値を生成する操作は、Realm API 関数であるincrementdecrementsetのみです。 他のすべての操作( incdecを含む)は、新しい 値を持つ非マネージド インスタンスを返します。

次の例では、 increment()decrement()set()操作を使用してMutableRealmIntプロパティを更新します。

// Open a write transaction
realm.write {
// Get the live object
val frog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
val counter: MutableRealmInt? = frog.fliesEaten
counter?.get() // 1
// Increment the value of the MutableRealmInt property
// ** Note use of decrement() with negative value **
counter?.increment(0) // 1
counter?.increment(5) // 6
counter?.decrement(-2) // 8
// Decrement the value of the MutableRealmInt property
// ** Note use of increment() with negative value **
counter?.decrement(0) // 8
counter?.decrement(2) // 6
counter?.increment(-1) // 5
// Set the value of the MutableRealmInt property
// ** Use set() with caution **
counter?.set(0)// 0
}

RealmAnyプロパティは不変です。 RealmAny値を更新するには、目的の値とタイプを持つプロパティの新しいインスタンスを作成する必要があります。 RealmAnyプロパティの追加の詳細については、「 RealmAny(混合)プロパティの作成 」を参照してください。

さらに、 RealmAnyプロパティから値を抽出するには、保存された型を知っている必要があります。 間違った型で getter メソッドを呼び出すと、Realm は例外をスローします。

Tip

条件式による多形データの処理

その値を抽出するには、保存された型を知っている必要があるため、 RealmAny型とその可能な内部値クラスを処理するにはwhen式を使用することをお勧めします。

val favoriteThings = frog.favoriteThings
when (favoriteThings.type) {
INT -> rating(favoriteThings.asInteger())
STRING -> description(favoriteThings.asString())
BYTE_ARRAY -> image(favoriteThings.asByteArray())
// Handle other possible types...
else -> {
// Debug or a perform default action
Log.d("ExampleHandler", "Unhandled type: ${favoriteThings.type}")
}
}

次の例では、各リスト要素の新しいインスタンスを作成して、 RealmAnyプロパティのリストを含むFrogオブジェクトをアップデートします。

// Find favoriteThing that is an Int
// Convert the value to Double and update the favoriteThing property
realm.write {
val kermit = query<Frog>().find().first()
val realmAny: RealmList<RealmAny?> = kermit.favoriteThings
for (i in realmAny.indices) {
val thing = realmAny[i]
if (thing?.type == RealmAny.Type.INT) {
val intValue = thing.asInt()
val doubleValue = intValue.toDouble()
realmAny[i] = RealmAny.create(doubleValue)
}
}
}
// Overwrite all existing favoriteThing properties
// ** Null clears the property value **
realm.write {
val frog = query<Frog>().find().first()
val realmAny: RealmList<RealmAny?> = frog.favoriteThings
realmAny[0] = RealmAny.create("sunshine")
realmAny[1] = RealmAny.create(Frog().apply { name = "Kermit Sr." })
realmAny[2] = null
}

注意

RealmAny プロパティ値を null でクリア

現在の値を削除するには、 nullRealmAnyプロパティに直接割り当てます。

オブジェクトタイプの定義方法によっては、サポートされている次のコレクション タイプのいずれかとして定義されるプロパティがある場合があります。

  • RealmList

  • RealmSet

  • RealmDictionary

コレクションは可変であり、対応する組み込み Kotlin クラスによってサポートされています。 書込みトランザクション (write transaction) 内でコレクション内の要素を追加および削除できます。

Tip

コレクションへの変更をリッスンする

変更をリッスンするための通知ハンドラーを登録できます。 詳細については、「 コレクション変更リスナーの登録 」を参照してください。

RealmList 内の要素は Kotlin MutableList と同様に更新できます。

次の例では、既存のFrogオブジェクトのRealmList要素をアップデートします。

realm.write {
// Get the live object
val realmList = query<Frog>("name = $0", "Kermit").first().find()!!.favoritePonds
realmList[0].name = "Picnic Pond"
realmList.set(1, Pond().apply { name = "Big Pond" })
}

RealmList要素の追加と削除の詳細については、「 RealmList の作成 」と「 RealmListからの要素の削除 」を参照してください。

RealmSet では Kotlin MutableSet と 同様に要素を追加、更新、削除できます。

次の例では、既存のFrogオブジェクトのRealmSet要素を反復処理して更新します。

// Find a frog in the realm
val kermit = realm.query<Frog>("name = $0", "Kermit").find().first()
val realmSet = kermit.favoriteSnacks
// Update the name of each snack in the set
for (snack in realmSet) {
realm.write {
findLatest(snack)?.name = snack.name.uppercase()
}
}
realm.write {
// Find all frogs who like rain
val frogsWhoLikeRain = realm.query<Frog>("favoriteWeather CONTAINS $0", "rain").find()
// Add thunderstorms to their favoriteWeather set
for (frog in frogsWhoLikeRain) {
val latestFrog = findLatest(frog)
latestFrog?.favoriteWeather?.add("thunderstorms")
}
}

RealmSet要素の追加と削除の詳細については、「 RealmSet プロパティの作成 」と「 RealmSetからの要素の削除 」を参照してください。

RealmDictionary では Kotlin MutableMap と 同様にキーと値をアップデートできます。

次の例では、次を更新します: RealmDictionary

// Find frogs who have forests with favorite ponds
val thisFrog = realm.query<RealmDictionary_Frog>("favoritePondsByForest.@count > 1").find().first()
// Update the value for a key if it exists
if (thisFrog.favoritePondsByForest.containsKey("Hundred Acre Wood")) {
realm.write {
findLatest(thisFrog)?.favoritePondsByForest?.set("Lothlorien", "Lily Pad Pond")
}
}
// Add a new key-value pair
realm.write {
findLatest(thisFrog)?.favoritePondsByForest?.put("Sherwood Forest", "Miller Pond")
}

RealmDictionaryエントリの追加と削除の詳細については、「 辞書プロパティの作成 」「 辞書のキーと値の削除 」を参照してください。

オブジェクトタイプの定義方法によっては、別の Realm オブジェクトを参照するプロパティがある場合があります。 これは 1 対多、対多、または逆の関係にすることができます。

また、ある Realm オブジェクトを別の Realm オブジェクトに直接埋め込み、 EmbeddedRealmObjectタイプのネストされたデータ構造を作成することもできます。 詳細については、このページの「 埋め込みオブジェクトの更新」セクションを参照してください。

Realm 内のオブジェクト間の関係を更新するには、関係を定義するプロパティを他のプロパティと同様に変更します。

次の例では、単一のPondオブジェクトを参照するfavoritePondプロパティと、別のFrogオブジェクトを参照するbestFriendプロパティを持つFrogオブジェクトがあります。

realm.write {
val kermit = query<Frog>("name == $0", "Kermit").find().first()
// Update a property on the related object
kermit.favoritePond?.name = "Big Pond"
// Assign a new related object
val newBestFriend = Frog().apply { name = "Froggy Jr." }
kermit.bestFriend = newBestFriend
}

対多の関係は、他のコレクションと同様に更新できます。 このページの「コレクション プロパティの更新 」セクションを参照してください。

次の例では、 Frogオブジェクトのセットを参照するfrogsThatLiveHereプロパティと、 Pondオブジェクトのリストを参照するnearByPondsプロパティを持つForestオブジェクトがあります。

realm.write {
val forest = query<Forest>().find().first()
// Update a property on a related object in the set
forest.frogsThatLiveHere.first().name = "Kermit Sr."
// Add a new related object to the list
forest.frogsThatLiveHere.add(Frog().apply { name = "Froggy Jr." })
}

逆の関係でオブジェクトにアクセスしてアップデートできます。 ただし、バックリンク コレクション自体を直接変更することはできません。 代わりに、関連するオブジェクトを変更すると、Realm は暗黙的な関係を自動的に更新します。 詳しくは、「 逆の関係の定義 」を参照してください。

次の例では、親Userオブジェクトと、 Post子オブジェクトのリストを参照するバックリンクpostsプロパティがあります。 バックリンクを介して親オブジェクトと子オブジェクトのプロパティを更新します。

realm.write {
// Update child objects through the parent
val parent = query<User>().find().first()
parent.posts[0].title = "Forest Life Vol. 2"
parent.posts.add(Post().apply { title = "Forest Life Vol. 3" })
// Update child objects (Realm automatically updates the backlink collection)
val child = query<Post>("title == $0", "Top Ponds of the Year!").find().first()
child.title = "Top Ponds of the Year! Vol. 2"
assertEquals("Top Ponds of the Year! Vol. 2", parent.posts[1].title)
// Update the parent object through the child
child.user[0].name = "Kermit Sr."
// ** You CANNOT directly modify the backlink collection **
val readOnlyBacklink: RealmResults<User> = child.user
}

オブジェクトを Realm にアップサートするには、 copyToRealm()を使用してプライマリキーを持つオブジェクトを挿入し、 新しいオブジェクト を作成する場合と同様に、 UpdatePolicyパラメーターを渡して、SDK が同じプライマリキーを持つ既存のオブジェクトを処理する方法を指定します。

  • UpdatePolicy.ALL: 同じプライマリキーで識別される既存のオブジェクトのすべてのプロパティを更新します。

  • UpdatePolicy.ERROR (デフォルト): 既存のオブジェクトのアップデートは許可されず、代わりに同じプライマリキーを持つオブジェクトがすでに存在する場合には例外がスローされます。 更新ポリシーを指定しない場合、Realm はデフォルトでこのポリシーを使用します。

更新ポリシーによっては、次のことが発生する可能性があります。

  • プライマリキーに一致するオブジェクトが存在しない場合、SDK は新しいオブジェクトを挿入します。

  • 同じプライマリキーを持つオブジェクトがすでに存在する場合、SDK は次のいずれかになります。

    • 同じプライマリキーで識別される既存のオブジェクトのすべてのプロパティを更新します。 プロパティが同じ値にアップデートされた場合でも、プロパティは変更リスナーでアップデートされたものとしてマークされることに注意してください。

    • オブジェクトが Realm にすでに存在することを示す例外をスローします。

次の例では、 UpdatePolicy.ALLを使用して、Realm にすでに存在するプライマリキーを持つFrogオブジェクトを挿入し、オブジェクトが正常にアップサートされていることを確認します。

realm.write {
val existingFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
assertEquals(existingFrog.name, "Kermit")
// Use copyToRealm() to insert the object with the primary key
// ** UpdatePolicy determines whether to update or throw an error if object already exists**
copyToRealm(Frog().apply {
_id = PRIMARY_KEY_VALUE
name = "Wirt"
age = 4
species = "Greyfrog"
owner = "L'oric"
}, UpdatePolicy.ALL)
val upsertFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
assertEquals(upsertFrog.name, "Wirt")
}

戻る

読み取り