【问题标题】:MongoDB Structure for message app消息应用程序的 MongoDB 结构
【发布时间】:2012-06-29 00:16:38
【问题描述】:

我正在思考一个用于处理消息应用程序的良好文档结构。

我基本上需要三种(或四种)对象:

  1. 用户(用户名、电子邮件、密码等)
  2. 联系人列表(包含不同的联系人或联系人组)
  3. 对话(对话是一些人之间的信息集合)
  4. 消息(包含消息正文、一些时间戳和创建者。)

我的想法是将联系人嵌入到用户文档中,并将消息嵌入到对话文档中:

1.用户

{
    username: 'dev.puS',
    usernameCanonical: 'dev.pus', // used for unique constraints
    email: 'developement.pus@gmail.com,
    emailCanonical: 'developement.pus@gmail.com,
    salt: 'some hash',
    password: 'hash with salt',
    logs: { last_login: 12.06.2008, last_password_reset: 04.03.2007 },
    state: { online: true, available: false },
    contacts: [ user_id1, user_id2, user_id3 ]
}

2。对话

{
    members: [ user_id1, user_id2 ],
    messages: [
        { author: user_2, body: 'Hi what's up' },
        { author: user_1, body: 'Nothing out here :(' },
        { author: user_2, body: 'Whanna ask some question on stackoverflow' },
        { author: user_1, body: 'Okay, lets go' }
    ]
}

你觉得这个架构怎么样?

我认为将它们分开会更好(这样每个文档都是自己的),因为每个文档都有不同的更新频率。但是我真的没有任何经验,所以听到一些建议会很好:)

问候

【问题讨论】:

  • MongoDB 模式本身永远不会是“好”或“坏”的。您需要详细说明您将要进行的查询和更新。只有这样,您才能评估给定模式是否适合这些操作模式。
  • 您还需要估计数据大小的分布,例如:平均而言,一个对话最多包含多少条消息?如果您想嵌入,这可能很重要。
  • 好的,我会记住这一点。这是一种常用的方法来缓存例如使用redis的消息,而不是在会话结束时将它们全部保存到mongo?我有点不确定对“非结构化”对象执行大量写入操作

标签: mongodb database-schema bson


【解决方案1】:

您的问题实际上是架构设计之一。我建议看看这个关于 MongoDB 模式设计的页面,以了解选择和权衡:http://www.mongodb.org/display/DOCS/Schema+Design

此外,您可能应该查看该文档“另请参阅”部分中的链接。我特别推荐视频演示。

最后,您可能应该查看此文档,以讨论消息/评论数据库的三种可能模式,包括每种设计的权衡:http://docs.mongodb.org/manual/use-cases/storing-comments/

【讨论】:

    【解决方案2】:

    我看到这个问题很老了,但是对于任何有兴趣的人来说,问了一个类似的问题并且一个答案看起来可行https://stackoverflow.com/a/30830429/132610

    Conversation : {
     id: 123,
     members: [ user_id1, user_id2 ]
    }
    Message { conversationId: 123, author: user_2, body: 'Hi what's up' }
    Message { conversationId: 123, author: user_1, body: 'Whanna ask some question on stackoverflow' }
    

    更新 #1

    1) 可扩展性:MongoDB 可以很好地扩展非常大的集合。每个集合数十亿条消息。有一种称为分片的技术可以让您将较大的集合拆分到多个节点。

    2) 阅读。由于 MongoDB 具有索引机制,因此读取可与任何经过微调的数据库引擎相媲美。所以阅读不会成为问题。特别是,当一个对话(组|房间)的参与者较少时,例如两个人互相发送消息。

    【讨论】:

    • 我脑子里有一个困惑,你(和其他所有人)说一个集合是Conversations,另一个集合是Messages。假设我们在消息传递中有 100 万用户,他们正在互相交谈,Messages 表可能达到数十亿个文档,mongodb 是否有能力管理这么大的文档集合,搜索响应时间呢?假设我们在数十亿条消息中搜索单个用户的最后 100 条消息,返回需要多长时间?
    • @InzamamMalik,我也有同样的问题!!你能找到“最佳实践”的答案吗?
    • 这对我来说是一个困惑。在私聊时间,我们需要找到“有没有私聊的成员是这两个人?”如果是,我们应该首先加载该对话的历史记录(例如 10 条最新消息),然后将消息发送到该对话。所以每次我们需要首先搜索用户订阅的所有私人对话。但是,如果一方被删除了该对话(取消订阅),那么我们不能再次订阅他/她。有没有关于这个话题的综合分析?
    【解决方案3】:

    这是我的建议

    {
    "_id" : ObjectId("5a9e9581a2147c0c0f00002e"),
    "id_members1" : "5a9e9581a2147c0c0f02345t",
    "id_members2" : "5a9e9581a2147c0c0f02134g",
    "name" : [ 
        "Omar", 
        "Mohamed"
    ],
    "messages" : [ 
        {
            "author" : "Omar",
            "body" : "salam 3likom",
            "create_at" : ISODate("2018-03-07T09:04:04.000Z")
        }, 
        {
            "author" : "Mohamed",
            "body" : "Wa3likom salam",
            "create_at" : ISODate("2018-03-07T09:04:04.000Z")
        }, 
        {
            "author" : "Mohamed",
            "body" : "wach teshak",
            "create_at" : ISODate("2018-03-07T09:04:04.000Z")
        }, 
        {
            "author" : [ 
                "Omar", 
                "Mohamed"
            ],
            "body" : "test msg",
            "create_at" : ISODate("2018-03-25T15:30:05.000Z")
        }
    ],
    "comments" : [ 
        null, 
        {
            "author" : [ 
                "Omar", 
                "Mohamed"
            ],
            "body" : "test msg",
            "create_at" : ISODate("2018-03-25T15:28:11.000Z")
        }, 
        {
            "author" : [ 
                "Omar", 
                "Mohamed"
            ],
            "body" : "test msg",
            "create_at" : ISODate("2018-03-25T15:28:31.000Z")
        }
    ]
    

    }

    【讨论】:

    • 每次你查询这个对象你会得到所有的消息吗?与 1Mi 消息的对话怎么样?单独收集消息不是更好吗?或者可能创建一个 cronjob 将旧消息移动到新集合中,并使用旧消息进行分页
    • 为什么要添加评论对象?另外,如果我们也想做大群聊,有什么建议吗?
    • mongoDb 中的数组大小有限制,如果我猜对了,我猜它是 4MB。所以这真的是一个糟糕的设计。查询数组内部的内容也会产生过多的复杂性。
    【解决方案4】:

    请看我的建议:

        Person : {
            person_id: '123',
            last_login: 12.06.2008,
            online: true
        }
    
    Conversation : {
     conversation_id: append the greater person_id to the lower person_id, // person_1_id =123 and person_2_id =124 then its 123124
    
    messages: [ 
            { message_id: 1, 
              message_text : 'Hi what's up',
              sender_id : 123,
              receiver_id: 124,
              timestamp : 12344567891
            },
            { message_id: 2, 
              message_text : 'fine',
              sender_id : 124,
              receiver_id: 123,
              timestamp : 12344567891
            }
           ]
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      • 2010-11-14
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 2014-04-09
      相关资源
      最近更新 更多