嵌入式文档中的mongodb限制

时间:2011-12-09 22:14:28

标签: mongodb document mongodb-php

我需要创建一个消息系统,一个人可以与许多用户进行对话。 例如,我开始与user2,user3和user4交谈,因此他们中的任何人都可以看到整个对话,如果对话在任何时间都不是私密的,任何参与者都可以将任何其他人添加到对话中。

我的想法是如何做到这一点。 我正在使用Mongo,我的想法是使用对话框作为实例而不是消息。

架构如下所示:

{
_id : ...., // dialog Id
'private' : 0 // is the conversation private
'participants' : [1, 3, 5, 6], //people who are in the conversation
'msgs' :[
  {
   'mid' : ...// id of a message
   'pid': 1, // person who wrote a message
   'msg' : 'tafasd' //message
  },
  ....
  {
   'mid' : ...// id of a message
   'pid': 1, // person who wrote a message
   'msg' : 'tafasd' //message
  }
]
}

我可以看到这种方法的一些优点 - 在大型数据库中,很容易找到某些特定会话的消息。 - 将人们添加到对话中会很容易。

但这是一个问题,我无法找到解决方案: 对话变得太长了(以skype为例)并且他们没有向你展示所有的对话,他们向你展示了一部分,之后他们向你展示了其他消息。 在其他情况下,跳过,限制解决了这种情况,但我怎么能在这里做到这一点?

如果不可能有什么建议吗?

2 个答案:

答案 0 :(得分:13)

The MongoDB docs解释如何选择数组元素的子范围。

db.dialogs.find({"_id": [dialogId]}, {msgs:{$slice: 5}}) // first 5 comments
db.dialogs.find({"_id": [dialogId]}, {msgs:{$slice: -5}}) // last 5 comments
db.dialogs.find({"_id": [dialogId]}, {msgs:{$slice: [20, 10]}}) // skip 20, limit 10
db.dialogs.find({"_id": [dialogId]}, {msgs:{$slice: [-20, 10]}}) // 20 from end, limit 10

您可以使用此技术仅选择与UI相关的消息。但是,我不确定这是一个好的架构设计。您可能需要考虑从“存档”消息中分离出“可见”消息。它可能使查询更容易/更快。

答案 1 :(得分:1)

如果您的对话会有很多消息,则需要注意:

  1. 您会注意到切片消息数组的性能会有显着降低,因为mongodb会加载所有这些消息,并会在返回驱动程序之前对列表进行切片。
  2. 此方法可能达到文档大小限制(现在为16MB)。
  3. 我的建议是:

    1. 使用两个集合:一个用于对话,另一个用于消息。
    2. 在消息中使用dbref进行对话(使用消息时间戳索引此字段,以便能够根据用户请求选择较旧的范围)。
    3. 每次对话另外使用capped collection。如果你像“对话_”
    4. 那样建立它,很容易找到它

      结果:

      • 您必须两次写入所有消息。但是进入单独的收藏是正常的。
      • 当您想要展示对话时,您只需要选择natural sort order中一个集合中的所有数据,这非常快。
      • 您的上限集合将自动存储上一封邮件并删除旧邮件。
      • 您可以通过查询主要邮件集合来显示有关用户请求的旧邮件。