在 MongoDB 领域同步中建模子集合
Modeling sub-collections in MongoDB Realm Sync
我是 MongoDB 和 MongoDB 领域同步的新手。我一直在关注 Realm Sync tutorial and Realm data model docs,但我想了解更多,所以我调整了 Atlas 集合结构如下。
Projects > Tasks // i.e. tasks is a sub-collection in each project.
我不知道如何提出可以支持 Atlas 子集合的 Realm Sync Schema。
我想到的最好的是一个模式,其中 Task
s 被建模为 Project
中的数组。但是,我担心对于任务很多的项目,这会达到 16MB(虽然很多!)文档限制。
{
"bsonType": "object",
"properties": {
"_id": {
"bsonType": "objectId"
},
"_partition": {
"bsonType": "string"
},
"name": {
"bsonType": "string"
},
"tasks": {
"bsonType": "array",
"items": {
"bsonType": "object",
"title": "Task",
"properties": {
"name": {
"bsonType": "string"
},
"status": {
"bsonType": "string"
}
}
}
}
},
"required": [
"_id",
"_partition",
"name",
],
"title": "Project"
}
期待如何以正确的方式对子集合建模。
编辑
这是我的客户端 Realm 模型。
import Foundation
import RealmSwift
class Project: Object {
@objc dynamic var _id: String = ObjectId.generate().stringValue
@objc dynamic var _partition: String = "" // user.id
@objc dynamic var name: String = ""
var tasks = RealmSwift.List<Task>()
override static func primaryKey() -> String? {
return "_id"
}
}
class Task: EmbeddedObject {
@objc dynamic var name: String = ""
@objc dynamic var status: String = "Pending"
}
关于CRUD操作,我只是新建一个项目,读取已有项目如下。
// Read projects
realm.objects(Project.self).forEach { (project) in
// Access fields
}
// Create a new project
try! realm.write {
realm.add(project)
}
您的代码看起来很棒,而且您的方向是正确的,所以这个答案更多的是关于建模的解释和建议,而不是硬代码。
首先,Realm 对象是 lazily loaded,这意味着它们仅在使用时加载。数以万计的对象对设备内存的影响很小。所以假设您有 10,000 个用户并且您 'load them all in'
let myTenThousandUsers = realm.objects(UserClass.self)
嗯,没什么大不了的。然而,这样做
let someFilteredUsers = myTenThousandUsers.filter { [=11=].blah == "blah" }
将(可能)造成问题 - 如果 returns 10,000 个用户 他们都加载到内存中 可能会使设备不堪重负。这是一个 Swift 函数和 'converting' 通常应避免使用 Swift 的领域惰性数据(取决于用例)
观察这段代码使用Swift.forEach
realm.objects(Project.self).forEach { (project) in
// Access fields
}
可能会导致问题,具体取决于对这些项目对象执行的操作 - 如果它们很多,将它们用作 tableView 数据源可能会很麻烦。
第二个是关于每个文档 16Mb 限制的问题。为清楚起见,Atlas 文档是这样的
{
field1: value1,
field2: value2,
field3: value3,
...
fieldN: valueN
}
其中值可以是任何 BSON 数据类型,例如其他文档、数组和文档数组。
在您的结构中,var tasks = RealmSwift.List<Task>()
其中任务是 embedded object。虽然概念上嵌入的对象是对象,但我相信它们计入单个文档限制,因为它们是嵌入的(如果我错了请纠正我);随着它们数量的增加,封闭文档的大小也会增加 - 请记住,16Mb 的文本是一个巨大的文本,因此 would/could 相当于每个项目数百万个任务。
简单的解决办法是不要嵌入它们,让它们独立存在。
class Task: Object {
@objc dynamic var _id: String = ObjectId.generate().stringValue
@objc dynamic var _partition: String = ""
@objc dynamic var name: String = ""
@objc dynamic var status: String = "Pending"
override static func primaryKey() -> String? {
return "_id"
}
}
那么每个可以16Mb,一个'unlimited number'可以关联一个项目。嵌入式对象的一个优点是一种级联删除,当父对象被删除时,子对象也被删除,但是从项目到任务是一对多的关系——删除一堆属于父对象的任务很容易。
哦 - 另一种不使用嵌入式对象的情况 - 特别是对于这个用例 - 它们不能具有索引属性。 Indexing 可以大大加快某些查询的速度。
我是 MongoDB 和 MongoDB 领域同步的新手。我一直在关注 Realm Sync tutorial and Realm data model docs,但我想了解更多,所以我调整了 Atlas 集合结构如下。
Projects > Tasks // i.e. tasks is a sub-collection in each project.
我不知道如何提出可以支持 Atlas 子集合的 Realm Sync Schema。
我想到的最好的是一个模式,其中 Task
s 被建模为 Project
中的数组。但是,我担心对于任务很多的项目,这会达到 16MB(虽然很多!)文档限制。
{
"bsonType": "object",
"properties": {
"_id": {
"bsonType": "objectId"
},
"_partition": {
"bsonType": "string"
},
"name": {
"bsonType": "string"
},
"tasks": {
"bsonType": "array",
"items": {
"bsonType": "object",
"title": "Task",
"properties": {
"name": {
"bsonType": "string"
},
"status": {
"bsonType": "string"
}
}
}
}
},
"required": [
"_id",
"_partition",
"name",
],
"title": "Project"
}
期待如何以正确的方式对子集合建模。
编辑
这是我的客户端 Realm 模型。
import Foundation
import RealmSwift
class Project: Object {
@objc dynamic var _id: String = ObjectId.generate().stringValue
@objc dynamic var _partition: String = "" // user.id
@objc dynamic var name: String = ""
var tasks = RealmSwift.List<Task>()
override static func primaryKey() -> String? {
return "_id"
}
}
class Task: EmbeddedObject {
@objc dynamic var name: String = ""
@objc dynamic var status: String = "Pending"
}
关于CRUD操作,我只是新建一个项目,读取已有项目如下。
// Read projects
realm.objects(Project.self).forEach { (project) in
// Access fields
}
// Create a new project
try! realm.write {
realm.add(project)
}
您的代码看起来很棒,而且您的方向是正确的,所以这个答案更多的是关于建模的解释和建议,而不是硬代码。
首先,Realm 对象是 lazily loaded,这意味着它们仅在使用时加载。数以万计的对象对设备内存的影响很小。所以假设您有 10,000 个用户并且您 'load them all in'
let myTenThousandUsers = realm.objects(UserClass.self)
嗯,没什么大不了的。然而,这样做
let someFilteredUsers = myTenThousandUsers.filter { [=11=].blah == "blah" }
将(可能)造成问题 - 如果 returns 10,000 个用户 他们都加载到内存中 可能会使设备不堪重负。这是一个 Swift 函数和 'converting' 通常应避免使用 Swift 的领域惰性数据(取决于用例)
观察这段代码使用Swift.forEach
realm.objects(Project.self).forEach { (project) in
// Access fields
}
可能会导致问题,具体取决于对这些项目对象执行的操作 - 如果它们很多,将它们用作 tableView 数据源可能会很麻烦。
第二个是关于每个文档 16Mb 限制的问题。为清楚起见,Atlas 文档是这样的
{
field1: value1,
field2: value2,
field3: value3,
...
fieldN: valueN
}
其中值可以是任何 BSON 数据类型,例如其他文档、数组和文档数组。
在您的结构中,var tasks = RealmSwift.List<Task>()
其中任务是 embedded object。虽然概念上嵌入的对象是对象,但我相信它们计入单个文档限制,因为它们是嵌入的(如果我错了请纠正我);随着它们数量的增加,封闭文档的大小也会增加 - 请记住,16Mb 的文本是一个巨大的文本,因此 would/could 相当于每个项目数百万个任务。
简单的解决办法是不要嵌入它们,让它们独立存在。
class Task: Object {
@objc dynamic var _id: String = ObjectId.generate().stringValue
@objc dynamic var _partition: String = ""
@objc dynamic var name: String = ""
@objc dynamic var status: String = "Pending"
override static func primaryKey() -> String? {
return "_id"
}
}
那么每个可以16Mb,一个'unlimited number'可以关联一个项目。嵌入式对象的一个优点是一种级联删除,当父对象被删除时,子对象也被删除,但是从项目到任务是一对多的关系——删除一堆属于父对象的任务很容易。
哦 - 另一种不使用嵌入式对象的情况 - 特别是对于这个用例 - 它们不能具有索引属性。 Indexing 可以大大加快某些查询的速度。