This page describes how to update an existing Realm object in a local or synced realm using the Kotlin SDK. To learn more about creating objects in a realm, refer to Create Realm Objects - Kotlin SDK.
Realm admite operaciones de actualización y upsert en objetos de Realm y objetos incrustados. Una operación upsert inserta una nueva instancia de un objeto o actualiza un objeto existente que cumple ciertos criterios. Para obtener más información, consulte Insertar una sección de objeto de reino en esta página.
No puedes actualizar objetos asimétricos. Esto se debe a que los objetos asimétricos son objetos especiales de solo escritura que no persisten en el realm. Para obtener información sobre cómo utilizar objetos asimétricos en tu aplicación, consulta Stream Data to Atlas - Kotlin SDK.
Nota
Write to a Synced Realm
The syntax to update an object in a realm is the same for a local or a synced realm. However, there are additional considerations that determine whether the write operation in a synced realm is successful. For more information, refer to Write Data to a Synced Realm - Kotlin SDK.
Operaciones de actualizar
All operations that modify a realm - including update and upsert operations - must be performed inside of a write transaction. Write transactions are passed to the realm's write() or writeBlocking() method. Within this callback, you can access a MutableRealm instance, and then update objects within the realm. For more information on write transactions and how Realm handles them, refer to Write Transactions.
Additionally, you can only modify live objects, which are only accessible inside of a write transaction. You can convert a frozen object to a live object in a transaction with mutableRealm.findLatest().
Ejemplo
Convert Frozen Object Before Modifying
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 } }
Update an Existing Object
Para modificar las propiedades de un objeto Realm o un objeto incrustado almacenado dentro de un realm:
Abra una transacción de escritura con realm.write() o realm.writeBlocking().
Get the live objects by querying the transaction's mutable realm for the objects that you want to modify using query():
Especifica el tipo de objeto Realm como un parámetro de tipo pasado a
query().(Optional) Filter the set of returned objects by specifying a query. If you don't include a query filter, you return all objects of the specified type. For more information on querying with the Kotlin SDK, refer to Read Realm Objects - Kotlin SDK.
Importante
Objects Must Be Live
Solo puede modificar objetos activos. Si tu query ocurre fuera de la transacción de escritura, debes convertir los objetos congelados en objetos activos en la transacción con
mutableRealm.findLatest().Modifique el objeto dentro de la transacción de escritura. Puede usar un bloque de aplicación. Para configurar varias propiedades a la vez. Todos los cambios se guardan automáticamente en el dominio cuando Realm confirma la transacción de escritura.
Nota
Actualizando cadenas o arreglos de bytes
Debido a que Realm opera sobre campos como un todo, no es posible actualizar directamente elementos individuales de las cadenas o arreglos de bytes. En cambio, se debe leer el campo completo, hacer la modificación a los elementos individuales y luego volver a guardar el campo completo en un bloque de transacción.
Actualizar un objeto de reino
To update a Realm object, query for the type using a filter that returns the specific object that you want to update. Then, modify the object properties.
Tip
Use Unique Identifying Information
Recomendamos filtrar utilizando información de identificación única, como un valor de llave primaria para asegurar que tu query devuelva el objeto correcto.
En el siguiente ejemplo, consultamos un objeto Frog por clave primaria, luego actualizamos las propiedades name y age:
// 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 }
Update an Embedded Object
You can update an embedded object by modifying individual properties or by overwriting the entire embedded object.
Tip
Access Embedded Objects with Dot Notation
Puedes utilizar la notación de puntos para acceder a las propiedades de objetos incrustados como si estuvieras en un objeto normal anidado. Para más información, consulta Filtrar por propiedad de objeto incrustado.
Para actualizar una o más propiedades en un objeto incrustado, obtenga el objeto principal o incrustado y vuelva a asignar sus propiedades en una transacción de escritura.
In the following example, we have a Contact object that contains an embedded EmbeddedAddress object. We update the embedded object properties in several operations:
// 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" }
Para sobrescribir completamente un objeto incrustado, asigne una nueva instancia del objeto incrustado a la propiedad principal en una transacción de escritura. Esto elimina el objeto incrustado existente.
In the following example, we have a Contact object that contains an embedded EmbeddedAddress object. We define a new EmbeddedAddress object and assign it to the parent property:
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 }
Update Multiple Objects
También puedes actualizar múltiples objetos en un realm:
Query a realm for a collection of objects with realm.query().
Abra una transacción de escritura con realm.write() o realm.writeBlocking().
Update elements of the set of RealmResults returned by the query.
val tadpoles = realm.query<Frog>("age <= $0", 2) for (tadpole in tadpoles.find()) { realm.write { findLatest(tadpole)?.name = tadpole.name + " Jr." } }
Update Realm Properties
Depending on how you define your object type, you might have properties that are special Realm-specific types.
Update a MutableRealmInt (Counter) Property
You can use the following Realm API functions to update a MutableRealmInt property value:
increment()decrement()set()
Estos métodos devuelven la propiedad MutableRealmInt con un valor mutado.
Tip
Use set() Operator with Caution
The set() operator overwrites any prior calls to increment() or decrement(). We do not recommend mixing set() with increment() or decrement(), unless fuzzy counting is acceptable for your use case.
Además de las funciones de la API de Realm, también puedes utilizar el siguiente conjunto de operadores y funciones infijas similares a las proporcionadas por la biblioteca estándar de Kotlin Longpara:
Unary prefix operators:
unaryPlus,unaryMinusIncrement and decrement operators:
inc,dec(not to be confused withincrementanddecrement)Arithmetic operators:
plus,minus,times,div,remEquality operators:
equalsComparison operators:
compareToBitwise functions:
shl,shr,ushr,and,or,xor,inv
However, these operators and infix functions do not mutate the instance on which they are called. Instead, they return a new unmanaged instance with the result of the operation.
Importante
Only Realm Methods Result in a Mutated Value
The only operations that result in a mutated value are the Realm API functions: increment, decrement, and set. All other operations (including inc and dec) return an unmanaged instance with a new value.
In the following example, we update a MutableRealmInt property with increment(), decrement(), and set() operations:
// 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 }
Update a RealmAny (Mixed) Property
RealmAny properties are immutable. To update a RealmAny value, you must create a new instance of the property with the desired value and type. For more information on adding RealmAny properties, refer to Create a RealmAny (Mixed) Property.
Additionally, you must know the stored type to extract the value from a RealmAny property. If you call a getter method with the wrong type, Realm throws an exception.
Tip
Handle Polymorphism with Conditional Expressions
Because you must know the stored type to extract its value, we recommend using a when expression to handle the RealmAny type and its possible inner value class.
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}") } }
In the following example, we update a Frog object that contains a list of RealmAny properties by creating new instances of each list element:
// 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 }
Nota
Borrar un valor de propiedad RealmAny con null
Puede asignar null directamente a una propiedad RealmAny para eliminar el valor actual.
Update Collection Properties
Depending on how you define your object type, you might have properties that are defined as one of the following supported Collection Types:
RealmListRealmSetRealmDictionary
Las colecciones son mutables y están respaldadas por sus respectivas clases incorporadas de Kotlin. Puede agregar y remover elementos en una colección dentro de una transacción de escritura.
Tip
Escuchar los cambios en una colección
You can register a notification handler to listen for changes. For more information, refer to Register a Collection Change Listener.
Update a RealmList
Puedes actualizar elementos en una RealmList como lo harías en una Kotlin MutableList.
In the following example, we update RealmList elements for an existing Frog object:
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" }) }
Para obtener más información sobre cómo añadir y eliminar elementos RealmList, consulta Crear una RealmList y Remover elementos de una RealmList.
Update a RealmSet
Puede agregar, actualizar y eliminar elementos en un RealmSet como lo haría en un MutableSet de Kotlin.
In the following example, we iterate through and update RealmSet elements for existing Frog objects:
// 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") } }
For more information on adding and removing RealmSet elements, refer to Create a RealmSet Property and Remove Elements from a RealmSet.
Actualizar un Diccionario
You can update keys and values in a RealmDictionary as you would a Kotlin MutableMap.
In the following example, we update a 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") }
For more information on adding and removing RealmDictionary entries, refer to Create a Dictionary Property and Remove Dictionary Keys/Values.
Actualizar relaciones
Dependiendo de cómo definas tu tipo de objeto Realm, podrías tener propiedades que referencien a otro objeto Realm. Esto puede ser una relaciónde uno a uno, de uno a varios o inversa.
You can also embed one Realm object directly within another to create a nested data structure with an EmbeddedRealmObject type. For more information, refer to Update an Embedded Object section on this page.
Update a To-One Relationship
You can update relationships between objects in a realm by modifying the properties that define the relationship the same way you would update any other property.
In the following example, we have a Frog object with a favoritePond property that references a single Pond object and a bestFriend property that references another Frog object:
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 }
Actualizar una relación a muchos
Puede actualizar las relaciones "de varios" de la misma manera que cualquier otra colección. Consulte la sección "Actualizar propiedades de colección" en esta página.
In the following example, we have a Forest object with a frogsThatLiveHere property that references a set of Frog objects and a nearByPonds property that references a list of Pond objects:
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." }) }
Update an Inverse Relationship
You can access and update objects in an inverse relationship. However, you cannot directly modify the backlink collection itself. Instead, Realm automatically updates the implicit relationship when you modify any related objects. For more information, refer to Define an Inverse Relationship.
En el siguiente ejemplo, tenemos un objeto principal User con una propiedad de vínculos de retroceso posts que hace referencia a una lista de Post objetos secundarios. Actualizamos las propiedades de los objetos principal y secundario mediante el vínculo de retroceso:
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 }
Upsert a Realm Object
To upsert an object into a realm, insert an object with a primary key using copyToRealm(), as you would when creating a new object, and pass an UpdatePolicy parameter to specify how the SDK handles existing objects with the same primary key:
UpdatePolicy.ALL: Update all properties on any existing objects identified with the same primary key.UpdatePolicy.ERROR(Predeterminado): No permite actualizar objetos existentes y, en su lugar, genera una excepción si ya existe un objeto con la misma clave principal. Si no especifica una política de actualización, Realm la usa de forma predeterminada.
Dependiendo de la política de actualización, puede ocurrir lo siguiente:
If no object exists that matches the primary key, the SDK inserts the new object.
Si ya existe un objeto con la misma llave primaria, el SDK puede:
Actualiza todas las propiedades en cualquier objeto existente identificado con la misma clave primaria. Tenga en cuenta que las propiedades se marcan como actualizadas en los escuchadores de cambios, incluso si la propiedad se actualizó al mismo valor.
Lanza una excepción que indica que ya existe un objeto en el realm.
In the following example, we attempt to insert a Frog object with a primary key that already exists in the realm with UpdatePolicy.ALL and confirm the object is successfully upserted:
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") }