Mongo DB在不同集合中的文档之间的关系

Ben*_*ann 10 mongoose mongodb node.js express

我还没准备好放手,这就是为什么我重新思考这个问题并编辑了Q(原文如下).


我正在使用mongoDB进行周末项目,它需要DB中的一些关系,这就是痛苦的全部:

我有三个系列:

Users
Lists
Texts
Run Code Online (Sandbox Code Playgroud)

用户可以拥有文本和列表 - 列表"包含"文本.文本可以在多个列表中.

我决定使用单独的集合(不是嵌入),因为子文档并不总是出现在其父级的上下文中(例如,所有文本,而不在列表中).

因此,需要做的是将属于某些列表的文本与这些列表完全相同.可以有无限的列表和文本,但列表相比较少.

与我最初想到的相反,我还可以将引用放在每个文本文档中,而不是列表文档中的所有text-id.它实际上会产生影响,因为我可以通过一个查询来查找列表中的每个片段.甚至可以索引该引用.

var TextSchema = new Schema({
      _id: Number,
      name: String,
      inListID: { type : Array , "default" : [] },
      [...]
Run Code Online (Sandbox Code Playgroud)

文本也很少出现在多个列表中,因此数组也不会真正爆炸.问题仍然存在,是否有可能扩展或实际上是用mongoDB实现它的更好方法?是否有助于限制文本可能的列表数量(可能)?是否有一个很少的配方:许多关系?

获得对已经完成的项目及其实现方式的参考甚至是很棒的(很少:很多关系).一旦需要某些关系,我无法相信每个人都会回避mongo DB.



原始问题

我将在目前为止看到的两个问题中将其分解:1)让我们假设一个列表由5个文本组成.如何引用列表中包含的文本?只需打开一个数组并将文本的_ids存储在那里?似乎那些阵列可能会长到月球和背部,减慢应用程序的速度?另一方面,文本需要没有列表,因此嵌入不是一个真正的选择.如果我想获得包含100个文本的列表的所有文本,怎么办...听起来像两个查询和一个包含100个字段的数组: - /.这种引用正确方法的方式是这样的吗?

var ListSchema = new Schema({
  _id: Number,
  name: String,
  textids: { type : Array , "default" : [] },
  [...]
Run Code Online (Sandbox Code Playgroud)

问题2)我看到这种方法是在删除文本时清理引用.它的引用仍然在包含文本的每个列表中,我不想遍历所有列表来清除那些死引用.或者我会吗?有没有一种聪明的方法来解决这个问题?只是让文本保持引用(它们在哪个列表中)只是移动问题,所以这不是一个选项.

我想我不是第一个遇到这种问题的人,但我也无法找到关于如何做到这一点的明确答案.

我也对这种引用(多对多?)的最佳实践以及特别是可伸缩性/性能的一般想法感兴趣.

mne*_*syn 6

关系通常不是一个大问题,尽管涉及关系的某些操作可能是.这在很大程度上取决于您尝试解决的问题,并且非常强烈地依赖于结果集的基数和键的选择性.

我编写了一个简单的测试平台,它可以根据典型的长尾分布生成数据.事实证明,MongoDB在关系方面通常比人们所认为的更好.

毕竟,关系数据库只有三个不同之处:

  • 外键约束:你必须自己管理这些,所以死链接有一些风险
  • 事务隔离:由于没有多文档事务,即使代码是正确的(从某种意义上它永远不会尝试创建死链接),也有可能创建无效的外键约束,但只是在运行时中断.此外,很难检查死链接,因为您可能正在观察竞争条件
  • 连接:MongoDB不支持连接,尽管手册子查询$in$in-clause中可以扩展到数千个项目,前提是参考值已编入索引,当然

如果您需要执行大型连接,即如果您的查询是真正的关系,并且您需要相应地加入大量数据,那么MongoDB可能不太合适.但是,关系数据库中所需的许多连接并不是真正的关系,它们是必需的,因为您必须将对象拆分为多个表,例如因为它包含一个列表.

"真正的"关系查询的一个例子可能是"找到所有购买了6月份营业额排名高的客户获得> 4星评价产品的客户".除非你有,基本上是能够支持这个查询一个非常特殊的模式,你很可能需要找到所有的订单,通过客户ID组他们,取前ñ效果,请使用这些使用查询评级$in,并使用另一个$in来找到实际的客户.不过,如果你可以限制自己到6月的10万客户,这是三次往返和一些快速$in查询.

只要您的查询受到RAM中的索引支持且网络不完全拥塞,典型的云硬件可能会在10-30ms的范围内.在这个例子中,如果数据太稀疏,事情变得混乱,即前10k用户几乎没有写过> 4星评论,这将迫使你编写足够聪明的程序逻辑来继续迭代第一步,既复杂又缓慢,但如果这是一个如此重要的场景,那么无论如何都可能有更适合的数据结构.