Nota
Modificar las propiedades del esquema de un dominio sincronizado
La siguiente página muestra cómo modificar las propiedades del esquema de un dominio local. Aprenda a... modificar las propiedades del esquema de un reino sincronizado.
Overview
Puede realizar cambios en el esquema de objetos después de crear el modelo de objetos de Realm. Según el tipo de cambios que realice, estos pueden aplicarse automáticamente o requerir una actualización manual del nuevo esquema.
Realm actualizará automáticamente el esquema de un objeto de Realm al agregar o eliminar una propiedad de un modelo de objeto de Realm. Solo necesita actualizar la versión del esquema.
Para todos los demás cambios de esquema, debe migrar manualmente las instancias antiguas de un objeto determinado al nuevo esquema.
Tip
Evitar la migración durante el desarrollo
Al desarrollar o depurar su aplicación, puede que prefiera eliminar el dominio en lugar de migrarlo. Use el indicador deleteRealmIfMigrationNeeded para eliminar la base de datos automáticamente cuando una discrepancia de esquema requiera una migración.
Nunca lance una aplicación a producción con esta bandera establecida en true.
Versión del esquema
Una versión de esquema identifica el estado de un esquema de dominio en un momento dado. Realm rastrea la versión de esquema de cada dominio y la utiliza para asignar los objetos de cada dominio al esquema correcto.
Las versiones del esquema son números enteros ascendentes que se pueden incluir opcionalmente en la configuración del dominio al abrirlo. Si una aplicación cliente no especifica un número de versión al abrir un dominio, este se configura de forma predeterminada como la 0 versión.
Importante
Incrementar versiones monótonamente
Las migraciones deben actualizar un dominio a una versión de esquema superior. El dominio generará un error si una aplicación cliente abre un dominio con una versión de esquema inferior a la actual, o si la versión de esquema especificada coincide con la actual, pero incluye esquemas de objetos diferentes.
Migración
En Realm, las actualizaciones de esquema se denominan migraciones. Una migración actualiza un reino y todos los objetos que contiene de una versión de esquema a una versión más reciente.
Al abrir un dominio existente con una versión de esquema posterior a la actual, puede proporcionar una función de migración que defina la lógica adicional necesaria para la actualización del esquema. Por ejemplo:
Establecer valores de propiedad
Combinar o dividir campos
Cambiar el nombre de un campo
Cambiar el tipo de un campo
La función tiene acceso al número de versión del reino y actualiza de forma incremental los objetos del reino para ajustarse al nuevo esquema.
Una migración local es una migración para un reino que no se sincroniza automáticamente con otro reino.
Nota
Para modificar las propiedades del esquema de un reino sincronizado, consulte Actualizar un modelo de datos en la documentación de Atlas Device Sync.
Actualizar automáticamente el esquema
Si la actualización de su esquema añade o elimina propiedades, Realm puede realizar la migración automáticamente. Solo necesita incrementar schemaVersion.
Agregar una propiedad
Para agregar una propiedad a un esquema:
Añade la nueva propiedad a la definición
RealmObject.Establezca la versión del esquema a través del generador RealmConfiguration.
Realm establece automáticamente los valores de las nuevas propiedades si el esquema de objeto actualizado especifica un valor predeterminado. Si el esquema de objeto actualizado no especifica un valor predeterminado, deberá establecer manualmente los valores de la nueva propiedad mediante una función de migración.
Ejemplo
Un realm que utiliza la versión de esquema 1 tiene un tipo de objeto Realm Person con las propiedades nombre, apellido y edad:
// Realm schema version 1 class Person : RealmObject { var firstName: String = "" var lastName: String = "" var age: Int = 0 }
El desarrollador agrega un campo email a la clase Person:
// Realm schema version 2 class Person : RealmObject { var firstName: String = "" var lastName: String = "" var age: Int = 0 var email: String? = null }
Para cambiar el realm y adaptarlo al esquema Person actualizado, el desarrollador establece la versión del esquema del realm en 2:
val config = RealmConfiguration.Builder( schema = setOf(Person::class) ) .schemaVersion(2) // Sets the new schema version to 2 .build() val realm = Realm.open(config)
Eliminar una propiedad
Para eliminar una propiedad de un esquema:
Eliminar la propiedad de la clase del objeto.
Establezca la versión del esquema a través del generador RealmConfiguration.
Eliminar una propiedad no afectará a los objetos existentes.
Ejemplo
Un reino que utiliza la versión de esquema 2 tiene un tipo de objeto Person con propiedades de nombre, apellido, edad y correo electrónico:
// Realm schema version 2 class Person : RealmObject { var firstName: String = "" var lastName: String = "" var age: Int = 0 var email: String? = null }
El desarrollador elimina el campo age de la clase Person:
// Realm schema version 3 class Person : RealmObject { var firstName: String = "" var lastName: String = "" // var age: Int = 0 var email: String? = null }
Para cambiar el realm y adaptarlo al esquema Person actualizado, el desarrollador establece la versión del esquema del realm en 3:
val config = RealmConfiguration.Builder( schema = setOf(Person::class) ) .schemaVersion(3) // Sets the new schema version to 3 .build() val realm = Realm.open(config)
Migrar esquema manualmente
Para actualizaciones de esquema más complejas, Realm requiere que migre manualmente instancias antiguas de un objeto determinado al nuevo esquema.
Al abrir el reino con el esquema actualizado, debe hacer lo siguiente en RealmConfiguration:
Incrementa la propiedad
schemaVersion.Define la lógica de migración utilizando migrationContext.
Modificar una propiedad
Para modificar una propiedad de un objeto (por ejemplo, cambiar el nombre, fusionar, dividir o cambiar el tipo de propiedad):
Cambiar la propiedad o propiedades en el esquema del objeto.
Abra el reino con una versión de esquema incrementada y una función de migración que asigna los objetos existentes para usar las nuevas propiedades.
En el siguiente ejemplo, se actualiza el esquema para cambiar un tipo de propiedad, fusionar dos propiedades en una nueva propiedad y cambiar el nombre de una propiedad existente:
// Realm schema version 1 (oldObject) class Person : RealmObject { var _id: ObjectId = ObjectId() var firstName: String = "" var lastName: String = "" var age: Int = 0 } // Realm schema version 2 (newObject) class Person : RealmObject { var _id: String = "" // change property type var fullName: String = "" // merge firstName and lastName properties var yearsSinceBirth: Int = 0 // rename property }
Luego, la función de migración define la lógica de migración para mapear datos entre las propiedades modificadas en el esquema de objeto antiguo y el nuevo esquema de objeto:
// Use the configuration builder to open the realm with the newer schema version // and define the migration logic between your old and new realm objects val config = RealmConfiguration.Builder( schema = setOf(Person::class) ) .schemaVersion(2) // Set the new schema version to 2 .migration(AutomaticSchemaMigration { it.enumerate(className = "Person") { oldObject: DynamicRealmObject, newObject: DynamicMutableRealmObject? -> newObject?.run { // Change property type set( "_id", oldObject.getValue<ObjectId>(fieldName = "_id").toString() ) // Merge properties set( "fullName", "${oldObject.getValue<String>(fieldName = "firstName")} ${oldObject.getValue<String>(fieldName = "lastName")}" ) // Rename property set( "yearsSinceBirth", oldObject.getValue<String>(fieldName = "age") ) } } }) .build() val realm = Realm.open(config)
Nota
Si tu actualización de esquema incluye convertir un RealmObject en un EmbeddedRealmObject, la función de migración debe garantizar que el objeto incrustado tenga exactamente un objeto padre vinculado a él. Los objetos incrustados no pueden existir independientemente de un objeto padre.
Otras tareas de migración
Para realizar otras migraciones de esquemas de reino, utilice las siguientes propiedades de la interfaz AutomaticSchemaMigration.MigrationContext:
oldRealm: El dominio tal como existía antes de la migración con la versión anterior del esquema. La API dinámica permite encontrar objetos de dominio mediante una cadena que representa su nombre de clase.
newRealm: el reino tal como existe después de la migración utilizando la nueva versión del esquema.
Cualquier objeto obtenido de oldRealm y newRealm es válido solo en el ámbito de la función de migración.
Al finalizar la migración, debe migrar todos los datos afectados por la actualización del esquema del dominio antiguo al nuevo. Los datos afectados por la actualización del esquema que no se migren se perderán.
val config = RealmConfiguration.Builder( schema = setOf(Person::class) ) .schemaVersion(2) .migration(AutomaticSchemaMigration { migrationContext -> val oldRealm = migrationContext.oldRealm // old realm using the previous schema val newRealm = migrationContext.newRealm // new realm using the new schema // Dynamic query for all Persons in old realm val oldPersons = oldRealm.query(className = "Person").find() for (oldPerson in oldPersons) { // Get properties from old realm val firstName: String = oldPerson.getValue( propertyName = "firstName", String::class ) // Get objects from old realm as dynamic realm objects val pet: DynamicRealmObject? = oldPerson.getObject( propertyName = "pets" ) } // Get migrated objects from the new realm as mutable objects val oldPerson: DynamicMutableRealmObject? = newRealm.findLatest(oldPersons[0]) oldPerson?.let { it.set("fullName", "Crow T. Robot") } // Create an object in the new realm and set property values val newPerson = newRealm.copyToRealm( DynamicMutableRealmObject.create( type = "Person", mapOf( "_id" to "123456", "fullName" to "Tom Servo", "yearsSinceBirth" to 33, ) ) ) }) .build() val realm = Realm.open(config)