我是 MongoDB 和 MongoDB Realm Sync 的新手。我在关注 Realm Sync tutorial和 Realm data model docs ,但我想了解更多,所以我调整了 Atlas 集合结构如下。
Projects > Tasks // i.e. tasks is a sub-collection in each project.
我不知道的是如何提出可以支持 Atlas 子集合的 Realm Sync Schema。
我想到的最好的是一个架构,其中 Task
被建模为 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 个用户,并且您“将他们全部加载”
let myTenThousandUsers = realm.objects(UserClass.self)
嗯,没什么大不了的。然而,这样做
let someFilteredUsers = myTenThousandUsers.filter { $0.blah == "blah" }
将(可能)产生问题 - 如果返回 10,000 个用户,他们都被加载到内存中 可能会使设备不堪重负。这是一个 Swift 函数,通常应避免使用 Swift 来“转换”Realms 惰性数据(取决于用例)
使用 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>()
其中 Task 是 embedded object .虽然概念上嵌入的对象是对象,但我相信它们计入单个文档限制,因为它们是嵌入的(如果我错了请纠正我);随着它们数量的增加,所附文档的大小也会增加 - 请记住,16Mb 的文本是一个巨大的文本,因此每个项目将/可能等同于数百万个任务。
简单的解决方案是不要嵌入它们,让它们独立存在。
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,并且'无限数量'可以与单个项目相关联。嵌入式对象的一个优点是一种级联删除,当父对象被删除时,子对象也被删除,但是从项目到任务是一对多的关系——删除一堆属于父对象的任务很容易。
哦 - 另一种不使用嵌入式对象的情况 - 特别是对于这个用例 - 它们不能具有索引属性。 Indexing可以大大加快一些查询。
关于ios - 在 MongoDB Realm 同步中建模子集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66603093/