我正在尝试创建一个消息系统,将每条消息写入 mongo 条目。我希望消息条目能够反射(reflect)发送消息的用户以及实际的消息内容。这是消息架构:
const MessageSchema = new Schema({
id: {
type: String,
required: true
},
messages: {
type: Array,
required: true
},
date: {
type: Date,
default: Date.now
}
});
这是我创建一个新条目或附加到现有条目的地方:
Message.findOne({ id: chatId }).then(message => {
if(message){
Message.update.push({ messages: { 'name': user.name, 'message': user.message } })
} else {
const newMessage = new Message(
{ id: chatId },
{ push: { messages: { 'name': user.name, 'message': user.message } } }
)
newMessage
.save()
.catch(err => console.log(err))
}
})
我希望最终结果看起来像这样:
id: '12345'
messages: [
{name: 'David', message: 'message from David'},
{name: 'Jason', message: 'message from Jason'},
etc.
]
这样的事情可能吗?如果可能的话,关于如何让它发挥作用有什么建议吗?
最佳答案
这个问题包含很多主题(至少在我看来)。我真的很想尝试将这个问题分解为其核心组件:
设计
正如 David 指出的(第一条评论),这里存在一个设计问题 - 不断增长的数组作为子文档并不理想(请参阅此 blog post 了解更多详细信息)。
另一方面 - 当我们想象一个单独的消息集合是什么样子时,它会是这样的:
_id: ObjectId('...') // how do I identify the message
channel_id: 'cn247f9' // the message belong to a private chat or a group
user_id: 1234 // which user posted this message
message: 'hello or something' // the message itself
这也不是那么好,因为我们根据时间重复 channel 和用户 ID。这就是为什么 bucket pattern被使用
那么......这里“最好”的方法是什么?
概念
现在最相关的问题是 - “此聊天应该支持哪些功能和负载?”。我的意思是,许多聊天仅支持消息显示,没有任何进一步的复杂性(例如在消息中搜索)。记住这一点,我们有可能在数据库中存储实际上不相关的信息。
这(几乎)就像在我们的数据库中存储二进制数据(例如图像)。我们可以这样做,但没有真正充分的理由。因此,如果我们不打算支持消息中的全文搜索,则根本没有必要将消息存储在数据库中......
但是..如果我们想支持全文搜索怎么办?好吧 - 谁说我们需要把这个任务交给我们的数据库?我们可以轻松下载消息(使用分页)并在客户端本身进行搜索操作(未找到关键字时,下载上一页并搜索它),从而减轻我们数据库的负载!
所以..从大小、功能和负载方面来看,消息似乎并不适合存储在数据库中(您可能会认为这个结论令人震惊)
重新设计
- 使用混合方法,将消息存储在带有分页的单独集合中(存储桶模式支持此方式,如 here 中所述)
- 将消息存储在数据库外部(因为您使用的是
Node.js
,您可以考虑使用 chunk store ),仅在数据库本身中保留对它们的引用 - 根据您的应用需求设置页面大小,并设置计算字段(例如:页面中当前消息的数量),以尽可能减轻数据库负载
架构
channels:
_id: ObjectId
pageIndex: Int32
isLastPage: Boolean
// The number of items here should not exceed page size
// when it does - a new document will be created with incremental pageIndex value
// suggestion: update previous page isLastPage field to ease querying of next page
messages:
[
{ userId: ObjectID, link: string, timestamp: Date }
]
messagesCount: Int32
最终结论
我知道 - 对于这样一个“简单”的问题来说,这似乎完全是多余的,但是 - Dawid Esterhuizen让我相信,从一开始就设计数据库来支持 future 的负载至关重要,而且总是比过度简化数据库设计要好
底线是,如果您打算有效地设计数据库,仍然需要回答“此聊天应该支持哪些功能和负载?”的问题(例如,找到您的设计以最优化的方式满足您的应用需求的最佳区域)
关于node.js - 使用 MongoDB 创建数组并推送到数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57838200/