【问题标题】:Chat document structure MongoDB聊天文档结构MongoDB
【发布时间】:2018-08-23 22:33:54
【问题描述】:

我正在构建一个聊天应用程序并使用 mongo 进行存储。我已经建立了一个文档结构。

{
    _id:
    sender_id:
    receiver_id:
    subject:
    created_at:
    updated_at:
    messages: [
        {
            _id:
            message:
            author_id:
            attatchments: [x,y,z],
            read:
            created_at:
        },
        {
            _id:
            message:
            author_id:
            attatchments: [x,y,z],
            read:
            created_at:
        }
    ]
}

就性能和文档大小而言,我很困惑这是否是一种好方法。有没有更好的方法或者这很好??

提前致谢

【问题讨论】:

  • 除非您明确要求,否则很难回答。为什么整个聊天消息数组的发送者和接收者都一样?
  • 不一样。对话只在两人之间。我主要保存 sender_id 和 receiver_id 。 author_id 将是发送者的 id。
  • 听起来不错!!想想……当有新消息时,您希望将整个数组发送给第二个客户端吗?还是只是最新到达的消息?如果是第二种情况,你要怎么查询呢?
  • 我只想要案例 2。我是 mongo 新手,不知道如何将 id 添加到子文档。

标签: database mongodb schema chat document


【解决方案1】:

在 Mongo 中,数据以您要查询的形式存储。

使用关系存储可以轻松解决聊天问题,但是如果您热衷于使用 Mongo,IMO 扁平结构是最好的。

您可以为每对发送者和接收者创建一个唯一的聊天 ID。将每个聊天消息存储为单独的文档。

{
    _id:
    chatId: 1234,
    sender_id:
    receiver_id:
    subject:
    updated_at:
    message: {
            message:
            messageId: 1,
            author_id:
            attatchments: [x,y,z],
            read:
            created_at:
            }
},
{
    _id:
    chatId: 1234,
    sender_id:
    receiver_id:
    subject:
    updated_at:
    message: {
            message:
            messageId: 2
            author_id:
            attatchments: [x,y,z],
            read:
            created_at:
            }
}

聊天将逐条消息(而不是批量)进行。 扁平结构让我可以快速读/写,但也可以帮助我提供搜索。

我什至可以提供分页功能,例如在窗口中显示最后 20 条消息,用户可以单击以加载更多消息。 (如下所示)

db.collection.find(
  {chatId: 1234, message.messageId: {$gte:1}
).sort({updated_at : -1})
.limit(20)

毫无疑问,文档的数量会增长得非常快,但是当你的字段有适当的索引时,Mongo 的读取总是很棒。



最后,再次阅读我的第一行。 “在 Mongo 中,数据以您想要查询的形式存储”。 如果您有正确的索引,那么拥有大量文档就不是问题,这是任何数据存储的基本质量。 考虑到 mongo 的数组运算符,我不赞成使用消息数组。

假设您每次聊天都有一个包含消息数组的文档,并且有 10K(或想象任何大量)带有附件的消息。当您查询聊天文档时,您想将它们全部加载到内存中吗?或者您只是对最新的 1 条、2 条或 20 条消息感兴趣?

现在,关于将单个集合拆分为两个关系集合的事情: IMO 适用于任何关系数据存储。


如何做出决定:

设计它的最佳方式是列出您的要求。如果您将聊天存储作为服务公开,请列出该服务将公开的端点。

在不久的将来您可能需要执行多少种不同类型的查询。

什么是搜索键。

您希望在单个 API 调用中返回多少条聊天消息。

等等 所有这些答案都将帮助您设计数据存储。

【讨论】:

  • 这不是正确的方法,因为每个对话文档都会增长..
  • @Rupesh 这就是我在上一行中提到的。我已经提供了我的看法和优点和缺点。我错过了什么吗?
  • 这就是我所担心的。但是如果我为消息创建另一个表,那么文档的数量会很大。
【解决方案2】:

如果你愿意,你可以像这样划分你的架构。

// coversation Schema
 {
    _id:
    sender_id:
    receiver_id:
    subject:
    created_at:
    updated_at:
    messagesId: [ ] //here you will store the _id of conversation occur between both. 
}



// Message Schema
 {   
   _id :             
   message:
   author_id:
   attatchments: [x,y,z],
   read:
   created_at:
 }

【讨论】:

  • 我想如果你想生成一个聊天列表,你可以通过 receiver_id 过滤:或者 sender_id 等于 my_id,或者保留两个具有字段 owner_id 的单独重复类型列表并对其进行查询跨度>
【解决方案3】:

对于聊天,最好将其规范化为关系模式。否则,如果您需要更新或做一些复杂的事情,管理嵌套的东西会很痛苦。

这是更好的实现聊天的方式,它也适用于 如果用户只想为他删除消息/对话。通过跟踪 deleted_by 属性如果 deleted_by 等于对话的参与者,则永久删除对话/消息!

对话模式

{
 id:String,
 participants:[String], //user ids
 created_at:Date,
 deleted_by:[String]
 ...
}

消息架构

{
 id:String,
 conversation_id:String,
 sender:String,
 content:String,
 read_by:[String] //user ids
 deleted_by:[String]
 ...
}

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 2016-07-24
    • 2016-02-29
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2020-09-24
    • 2015-04-13
    • 1970-01-01
    相关资源
    最近更新 更多