Cod*_*key 2 database-design mongoose mongodb
具体来说,我正在考虑一个聊天应用程序,其中 aUser有很多Chats,每个Chat都有很多Messages。我将如何表达这种Chat --has-Many--> Message关系?
最初,我以为我会将MessageID 引用列表存储在上Chat,例如Chat文档可能看起来像
{
_id: ObjectId('507f191e810c19729de860d5'),
title: 'Jack V, Kyle R, Sam P',
messages: [ObjectId('507f191e810c19729de860ea'), ...],
createdAt: 1546284204867
}
Run Code Online (Sandbox Code Playgroud)
这样,$push每次发送消息或$pull删除消息时,我都需要访问该数组。使代码更加复杂和晦涩,但仍然可行。
然后我从MongoDB 文档中读到,这种方法只有在数组很小并且增长有限时才有效。为了避免可变的、不断增长的数组,最好将refMessage保留chatId回其父级Chat
{
_id: ObjectId('507f191e810c19729de860ea'),
body: 'Hey Kyle! Mind if I ask ya a favor?',
chatId: ObjectId('507f191e810c19729de860d5'),
createdAt: 1546284204869
}
Run Code Online (Sandbox Code Playgroud)
最后,如果我想获取消息与猫鼬聊天,
const chatId = '507f191e810c19729de860d5'
// 1. through IDs array
Chat.findById(chatId).populate('messages').execPopulate()
// or
// 2. through ID ref
Message.find({ chatId })
Run Code Online (Sandbox Code Playgroud)
根据我的理解,
Message文档,然后才读取它们Message文档(可能是数百万)并比较chatId每个文档的属性这与在 MongoDB中读取比写入更昂贵的事实一致。我的说法正确吗?如果是这样,为什么大多数资源都推荐方法#2?我在MDN 文档(见黄框)、MongoDB 开发人员的 50 条提示和技巧以及 MongoDB 文档中看到了它。
对于一对多关系,在父模型上维护一组 ID 更好,还是在每个子模型上都有一个 ID ref 更好?
写入更新实际上非常昂贵。插入新文档很快,但更新需要一些时间,因为您执行读取和写入操作。如果O(r)是“读”O(w)的时间复杂度和“写”的时间复杂度,则更新为O(r+w)。无论如何,如果您在查询的字段上建立了索引,读取实际上也非常高效,因此通常不需要担心。要遵循的一般建议是将您的更新保持在最低限度,而读取和插入是可以的,尽管只要您的索引良好,这些操作都不是真正的问题。
除此之外,我不建议将您的Messages非规范化到Chat文档中。文档的大小上限为 16MB,因此如果聊天变得特别大,那么 MongoDB 将无法处理。即使它从未超过该限制,您也无法优化消息检索——任何时候您想要加载聊天,您都需要一次获取所有消息,但在大多数现实情况下,您只需要检索例如最后几十条消息并根据需要加载更多消息!此外,将您的消息保存为单独的文档将允许您执行其他有用的任务,例如搜索和仅显示特定人员发送的消息、跳到特定时间点、清除早于给定日期的所有文档、创建 TTL索引以自动删除旧消息等。
因此,就潜在的功能、性能、文档大小限制,甚至只是易于管理而言,将Message父级引用到其对应的单独文档Chat是首选方法。
| 归档时间: |
|
| 查看次数: |
680 次 |
| 最近记录: |