ios - 在 MongoDB Realm 同步中建模子集合

标签 ios swift mongodb realm mongodb-realm

我是 MongoDB 和 MongoDB Realm Sync 的新手。我在关注 Realm Sync tutorialRealm 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/

相关文章:

ios - 使用 Swift 自定义 TableView 的页眉和页脚

ios - 获取核心数据关系的类型

ios - Dropzone 在 iOS 11 上失败

ios - 解析 PFUser.currentUser 返回 nil - Swift

ios - 类型 'String' 的值没有成员 'stringByAppendingPathComponent'

swift - iOS 和 Swift : ViewController class is defined, 但它是什么时候创建为对象的?

java - mongo 3.3 中的 DBCollection save() 等效项

ios - iCloud 和核心数据不工作 - URLForUbiquityContainerIndentifier 是零

mongodb - 使用 Mongo 恢复将集合导入到非本地地址

mongodb - 将文档数字字段更新为值 0 不起作用