MongoDB中嵌入式文档的限制

7
我需要创建一个信息系统,使一个人可以与多个用户进行对话。例如,我开始与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个回答

16

MongoDB文档解释了如何选择数组元素的子范围。

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相关的消息。但是,我不确定这是否是一个好的模式设计。您可能需要考虑将“可见”消息与“已归档”消息分开。这可能会使查询变得更加容易/快速。


没问题。如果我的回答解决了你的问题,请将答案标记为已选中。这将给我积分,并使其他用户更有可能回答你未来的问题 :) - jmacinnes

3

如果你的对话将有很多很多条消息,那么需要注意以下几点:

  1. 当你对消息数组进行切片时,你会发现性能显著降低,因为mongodb会将所有消息都加载并在返回给驱动程序之前对列表进行切片。
  2. 这种方法可能会达到文档大小限制(目前为16MB)。

我的建议是:

  1. 使用两个集合:一个用于对话,另一个用于消息。
  2. 在消息中使用dbref引用对话(使用消息时间戳对此字段进行索引,以便能够选择用户请求的旧范围)。
  3. 另外,对于每个对话使用单独的capped collection。如果将其构建为“conversation_”,则很容易按名称找到它。

结果:

  • 你需要将所有消息写两次。但是写入不同的集合是正常的。
  • 当你想要显示对话时,你只需要从一个集合中选择所有数据,并按自然排序顺序排序,这非常快速。
  • 你的capped collections将自动存储最新的消息并删除旧的消息。
  • 你可以通过查询主消息集合来显示用户请求的旧消息。

@SalvadorDali 不用担心大量的集合。选择正确的集合非常快速,而且在数量上没有理论限制。但你是对的,支持这么多的集合会很困难。现在我建议使用一个巨大的有上限的集合,并在对话上添加附加索引。这种情况下会有两个额外的问题:一些旧的对话将加载而没有任何先前的消息,并且在有上限的集合中添加索引并不是很好。 - lig
如果将它们分开到另一个数据库中,处理大量集合可能会更容易。就文档大小而言,拥有一堆约1MB大小的巨大文档甚至不好。因为这会降低驱动程序性能、复制和分片性能。个人而言,我永远不会将对话存储在一个文档中。存在许多可能的问题:搜索消息、共享或复制单个消息等。 - lig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接