Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ / /

使用 Device Sync 对数据建模 - Kotlin SDK

在此页面上

  • 定义 Device Sync 数据模型
  • 从客户端应用程序生成模式
  • 使用现有 Atlas 数据生成模式
  • Device Sync 要求
  • Realm 对象映射
  • Realm 关系映射
  • 映射对一关系
  • 对多关系
  • 反向关系
  • 嵌入式对象
  • 模式类型映射列表
  • Kotlin 类型
  • BSON类型
  • Realm 类型

本页介绍 Device Sync Realm 数据模型,以及如何使用该模型将数据从 Device Sync 使用的 App Services 模式映射到客户端中 Kotlin SDK 使用的 Realm 模式。

此页面不会

有关Device Sync的详细说明,请参阅Atlas App Services文档中的 Atlas Device Sync入门

提示

本页的“模式类型映射列表”部分中的表提供了有关支持的数据类型及其在Realm和App Services之间映射方式的快速参考。 有关更全面的资源,请参阅App Services文档中的数据模型映射

Atlas Device Sync Realm 数据模型由以下模式定义,允许 Device Sync 在客户端和 Atlas 之间映射数据:

  • Realm 模式:应用中的客户端对象模型,它使用 Kotlin SDK 将数据定义为 Kotlin 类。

  • App Services 模式 : Atlas App Services中的服务器端模式,用于定义BSON格式的数据。 有关更多信息,请参阅App Services文档中的模式

在同步数据时,Device Sync 使用这些模式来验证对象并在 Kotlin 和 BSON 格式之间转换对象。 当您从客户端同步数据时,Device Sync 会自动将 Realm Kotlin 数据类型转换为 BSON。 然后,当客户端设备通过 Device Sync 从 Atlas 同步数据时,SDK 会将 BSON 数据转换回 Kotlin 对象。

要使用 Device Sync,必须定义 Realm 模式和 App Services 模式,并且这两个模式必须一致。

您可以先在客户端应用程序或 Atlas 中定义模式,具体取决于您的偏好和使用案例。 然后,您可以使用匹配的对象模型生成相应的模式。

如果正在开发新的客户端应用程序,您可能希望迭代客户端应用程序中的数据模型。 直接在客户端应用代码中定义对象模型后,可以在 App Services 中启用开发模式以自动生成匹配的 App Services 模式。

开发模式是一种配置设置,当您从客户端同步数据时,允许Device Sync根据客户端数据模型推断和更新模式。 有关更多信息,请参阅App Services文档中的开发模式

如果您正在开发一个客户端应用程序,该应用程序需要处理Atlas中已存在的数据,则可以从该数据生成模式,然后生成要在Kotlin客户端应用中使用的 SDK对象模型。 要学习;了解更多信息,请参阅App Services文档中的使用客户端应用程序同步Atlas中的数据

要成功同步对象,有一些要求。 如前所述,您必须具有匹配的 Realm 和 App Services 模式,其中包含要同步的对象。

此外,Device Sync 要求:

  • 您的对象模型必须有一个名为 _id主键字段。 它的类型可以是StringIntObjectId 。 Device Sync 使用它来识别 Atlas 集合中的对象。

    如果对象没有定义_id字段,Realm 会抛出以下模式验证错误: There must be a primary key property named '_id' on a synchronized Realm

  • 每个类必须至少有一个可查询字段。

    启用开发模式后,您在客户端订阅查询中包含的字段将自动添加为 Atlas 中的可查询字段。 有关使用 Kotlin SDK 配置订阅的更多信息,请参阅订阅概述。

Realm 对象是 Realm 模式中定义的 Kotlin 类的唯一命名实例,用于确定该类型对象的属性和关系。

App Services 通过以下方式将 Realm 对象映射到 Atlas:

  • Realm 对象名称映射到链接的 Device Sync 数据源中的 Atlas collection。请注意以下事项:

    • 当开发模式启用时,App Services 会自动为您同步的每个新 Realm 对象类型创建 collection 和模式。

    • 嵌入式对象不会存储在Atlas中自己的集合中。 这是因为它们不能存在于其父对象类型之外。 有关更多信息,请参阅本页的嵌入式对象部分。

  • Realm 对象模式映射到相应的 collection 中的 App Services 模式。

在以下示例中, FrogPond对象的基本属性在 Realm 模式中定义:

Frog 和 Pond Realm 对象
// Maps to `Frog` collection
class Frog : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var age: Int? = null
}
// Maps to `Pond` collection
class Pond : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
}

在 Atlas 中,我们可以看到这些 Realm 对象类型如何映射到相应的 App Services 模式——每个对象都映射到各自的 collection。我们还看到了符合此Realm 数据模型的青蛙和池塘对象的示例:

App Services 中的 collection
{
"title": "Frog",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"age": {
"bsonType": "long"
},
"name": {
"bsonType": "string"
}
}
}
App Services 中的 Pond collection
{
"title": "Pond",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"name": {
"bsonType": "string"
}
}
}
Atlas中的 Frog对象示例
{
"_id": ObjectId("5af712eff26b29dc5c51c60f"),
"name": "Kermit",
"age": 42
}
Atlas中的 Pond对象示例
{
"_id": ObjectId("5af714eff24b294c5251cf04"),
"name": "Kermit's Pond"
}

您的 Realm 对象模型可能包括对象之间的关系。 主要有两种类型的关系:

  • 一对一关系:一个对象以特定方式与不超过一个其他 Realm 对象相关。

  • 对多关系:一个对象以特定方式与多个 Realm 对象相关。

关系由引用其他 Realm 对象主键的属性映射。

有关在Atlas App Services 模式中进行关系建模的更多信息,请参阅 Atlas App Services文档中的 关系 。

一对一关系将一个属性映射到另一个 Realm 对象的单个实例。 对一关系必须是可选的。 有关如何在 Kotlin SDK 中定义对一关系的更多信息,请参阅定义对一关系属性。

使用上例中的对象,考虑Frog可以有一个最喜欢的池塘的情况。 我们可以向Frog模型添加一个favoritePond属性,该属性是指向Pond对象的可选链接。

与 Pond 具有一对一关系的 Frog
class Frog : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var age: Int? = null
// To-one relationship (MUST be optional)
var favoritePond: Pond? = null
}

在 App Services 模式中,我们看到新属性转换为字段favoritePond

  • 该字段不在required数组中,因为它是可选属性。

  • 其类型是一个objectId PondPond,链接到单独的collection中的特定对象。这是因为我们将Pond模型上的主键定义为objectId

Pond模式保持不变。 由于这是一种对一关系,因此是一种单向关系; PondFrog没有关系。

应用程序服务模型
{
"title": "Frog",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"age": {
"bsonType": "long"
},
"favoritePond": {
"bsonType": "objectId"
},
"name": {
"bsonType": "string"
}
}
}

对多关系将一个属性映射到另一个 Realm 对象的零个或多个实例。 有关如何在 Kotlin SDK 中定义对多关系的更多信息,请参阅定义对多关系属性。

考虑另一种情况,其中Frog可以有许多而不是一个最喜欢的池塘。 我们将一个favoritePonds属性添加到Frog模型中,该模型是Pond对象的列表。 如果青蛙没有最喜欢的池塘,则这是一个空列表。 当青蛙喜欢上池塘时,我们可以创建新的Pond对象并将它们附加到青蛙的favoritePonds列表中。

与 Pond 具有对多关系的 Frog
class Frog : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var age: Int? = null
// To-many relationship (can have many ponds)
var favoritePonds: RealmList<Pond> = realmListOf()
}

在 App Services 模式中,我们看到新属性转换为favoritePonds字段,其中包含与 Frog 对象相关的所有Pond 对象:

  • 该字段不在required数组中,因为它是可选属性。

  • 此字段的类型是objectId类型的数组。这是因为我们将Pond模型上的主键定义为objectId

同样, Pond模式不会更改,因为PondFrog没有关系。

应用程序服务模型
{
"title": "Frog",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"age": {
"bsonType": "long"
},
"favoritePonds": {
"bsonType": "array",
"items": {
"bsonType": "objectId"
}
},
"name": {
"bsonType": "string"
}
}
}

反向关系将对象链接回在定义的对一或对多关系(称为反向链接)中引用该对象的任何其他对象。 有关 Kotlin SDK 中如何定义反向关系的更多信息,请参阅定义反向关系。

App Services 模式支持反向关系。 这是因为反向关系表示 Realm 中的一种隐式关系,会在修改反向链接时自动更新。 这意味着您无法直接设置反向关系的值,并且 Atlas 中不存在该关系。 相反,Realm 会根据您的 Realm 对象模型在客户端应用程序中为您派生并更新这些关系。

考虑Pond对象与Frog对象具有反向关系的情况。

与青蛙具有反向关系的池塘
class Pond : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
// Backlink to the `Frog` that has this `Pond` as its favorite
val frog: RealmResults<Frog> by backlinks(Frog::favoritePonds)
}
class Frog : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var age: Int? = null
// To-many relationship (can have many ponds)
var favoritePonds: RealmList<Pond> = realmListOf()
}

在 App Services 模式中,我们通过favoritePonds属性看到FrogPond具有多对多关系。 但是,表示与Pond模型中的Frog反向关系的frog属性存在。 这是因为在 Atlas 中无法显式定义反向关系。 但是,每当您在关系中添加或删除对象时,Realm 都会自动更新它。

应用程序服务模型
// `Pond` schema in App Services DOES NOT contain the
// `frog` inverse relationship property
{
"title": "Pond",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"name": {
"bsonType": "string"
}
}
}
{
"title": "Frog",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"age": {
"bsonType": "long"
},
"favoritePonds": {
"bsonType": "array",
"items": {
"bsonType": "objectId"
}
},
"name": {
"bsonType": "string"
}
}
}

嵌入式对象表示单个特定父对象内部的嵌套数据。 您可以采用与定义关系相同的方式从父Realm 对象类型引用嵌入式对象类型。有关如何在 Kotlin SDK 中定义嵌入式对象的更多信息,请参阅定义嵌入式对象。

但是,与常规 Realm 对象不同,嵌入式对象不会存储在 Atlas 中自己的 collection 中。相反,它们存储为父对象文档的一部分,并且无法在父对象之外进行访问。

在以下示例中,我们有一个带有favoritePond属性的Frog对象,该属性引用单个嵌入式Pond对象,还有一个带有forestPonds关系属性的Forest对象,该对象引用许多嵌入式Pond对象的列表:

具有嵌入式池塘关系的青蛙和森林
class Frog : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
var age: Int? = null
// Embed a single object (MUST be optional)
var favoritePond: EmbeddedPond? = null
}
class Forest : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = ""
// Embed multiple objects (can have many ponds)
var forestPonds: RealmList<EmbeddedPond> = realmListOf()
}
class EmbeddedPond : EmbeddedRealmObject {
var name: String? = null
}

在 App Services 模式中,我们看到嵌入式对象映射到每个父类型中的文档:

应用程序服务模型
{
"title": "Frog",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"age": {
"bsonType": "long"
},
"favoritePond": {
"title": "EmbeddedPond",
"type": "object",
"required": [],
"properties": {
"name": {
"bsonType": "string"
}
}
},
"name": {
"bsonType": "string"
}
}
}
{
"title": "Forest",
"type": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"forestPonds": {
"bsonType": "array",
"items": {
"title": "EmbeddedPond",
"type": "object",
"required": [],
"properties": {
"name": {
"bsonType": "string"
}
}
}
},
"name": {
"bsonType": "string"
}
}
}

下表演示了Realm对象类型如何映射到相应的Atlas App Services模式BSON类型。 有关支持的Atlas App Services 模式类型及其映射和可用属性的完整列表,请参阅 Atlas App Services文档中的 数据模型映射 。

下表列出了支持的 Kotlin 数据类型,以及声明的属性如何在 Realm 模式和 App Services 模式之间映射的示例。

有关 Kotlin SDK 支持的 Kotlin 数据类型以及如何在 Realm 数据模型中定义这些数据类型的更多信息,请参阅Kotlin 数据类型。

Kotlin 数据类型
Realm 对象
应用程序服务模型
String
var stringReq: String = ""
"stringReq": {
"bsonType": "string"
}
Byte
var byteReq: Byte = 0
"byteReq": {
"bsonType": "long"
}
Short
var shortReq: Short = 0
"shortReq": {
"bsonType": "long"
}
Int
var intReq: Int = 0
"intReq": {
"bsonType": "long"
}
Long
var longReq: Long = 0L
"longReq": {
"bsonType": "long"
}
Float
var floatReq: Float = 0.0f
"floatReq": {
"bsonType": "float"
}
Double
var doubleReq: Double = 0.0
"doubleReq": {
"bsonType": "double"
}
Boolean
var boolReq: Boolean = false
"boolReq": {
"bsonType": "bool"
}
Char
var charReq: Char = 'a'
"charReq": {
"bsonType": "long"
}

下表列出了支持的 MongoDB BSON 数据类型,以及声明的属性如何在 Realm 模式和 App Services 模式之间映射的示例。

有关 Kotlin SDK 支持的 MongoDB BSON 数据类型以及如何在 Realm 数据模型中定义这些数据类型的更多信息,请参阅Kotlin 数据类型。

MongoDB BSON 类型
Realm 对象
应用程序服务模型
var objectIdReq: ObjectId = ObjectId()
"objectIdReq": {
"bsonType": "objectId"
}
Decimal128
var decimal128Req: Decimal128 = Decimal128("123.456")
"decimal128Req": {
"bsonType": "decimal"
}

下表列出了支持的 Realm 特定数据类型,以及声明的属性如何在 Realm 模式和 App Services 模式之间映射的示例。

有关 Kotlin SDK 支持的 Realm 特定数据类型以及如何在数据模型中定义这些数据类型的更多信息,请参阅Kotlin 数据类型。

Realm 特定类型
Realm 对象
应用程序服务模型
var uuidReq: RealmUUID = RealmUUID.random()
"uuidReq": {
"bsonType": "uuid"
}
var realmInstantReq: RealmInstant = RealmInstant.now()
"realmInstantReq": {
"bsonType": "date"
}
var realmAnyOpt: RealmAny? = RealmAny.create("foo")
"realmAnyOpt": {
"bsonType": "mixed"
}
var mutableRealmIntReq: MutableRealmInt = MutableRealmInt.create(0)
"mutableRealmIntReq": {
"bsonType": "long"
}
var listReq: RealmList<CustomObjectType> = realmListOf()
"listReq": {
"bsonType": "array",
"items": {
"bsonType": "uuid"
}
}
var setReq: RealmSet<String> = realmSetOf()
"setReq": {
"bsonType": "array",
"uniqueItems": true,
"items": {
"bsonType": "string"
}
}
var dictionaryReq: RealmDictionary<String> = realmDictionaryOf()
"dictionaryReq": {
"bsonType": "object",
"additionalProperties": {
"bsonType": "string"
}
}
var realmObjectPropertyOpt: CustomObjectType? = null
"realmObjectPropertyOpt": {
"bsonType": "<PRIMARY_KEY_TYPE>"
}
var embeddedProperty: EmbeddedObjectType? = null
"embeddedProperty": {
"title": "EmbeddedObjectType",
"type": "object",
"required": [],
"properties": {
"name": {
"bsonType": "string"
}
}
}

后退

更改对象模型