【问题标题】:MongoDB: Populate parent using array of children vs search children by parent IDMongoDB:使用子元素数组填充父元素与通过父 ID 搜索子元素
【发布时间】:2020-08-26 00:52:41
【问题描述】:

我正在与我的经理就数据库结构发生争执。

我们需要创建一个具有多个子对象的父类型对象,并查询属于该父对象的所有子对象的列表。

我想在父对象中使用一组子 ObjectId,它们是在创建子对象时添加的。可以使用 FindById 找到父列表,然后可以使用 populate() 填充子列表。

我的经理坚持不在父对象中存储一个子数组,而只是将父对象的id作为一个字段存储在每个子对象中,然后通过搜索所有子对象得到列表具有父 ID 的对象。他声称这将同样快,因为“无论如何填充只是通过 id 搜索对象”。

但是,在我看来,它会这么快是不可思议的。 _id 字段的全部意义不在于索引文件的位置以便快速检索吗?与在整个数据库中搜索给定字段与给定值匹配的对象相比,查找具有 _id 的对象列表不应该总是更快且更具可扩展性吗?

在这种情况下不使用填充有什么理由吗? (当然,在子对象中存储对父对象的引用也是一种选择 - 但他坚持不根本不将子对象数组存储在父对象中。)

【问题讨论】:

  • 如果父级的嵌入文档有限,那么您应该将子级直接存储在父级中。如果没有,那么在孩子身上有父母的身份证是一个更好的方法。

标签: mongodb performance indexing mongoose-populate


【解决方案1】:

最好的方法不是一个简单的选择,它取决于数据的性质、您对未来数据集的期望以及您现在和将来如何查询数据。

将每个子 ID 存储在父数组中绝对是一个可行的选择。这使得检索诸如“这个父母有多少孩子?”之类的信息变得很容易。或“这个父母是否包括这两个孩子?”。它还简化了对子项的分页,因为客户端在检索父项时将接收所有子项 ID 值,并且可以根据需要检索尽可能多的子项记录以进行显示。在父节点的数组中存储其他数据,例如子节点名称和添加日期,意味着客户端可以有足够的信息来显示指向每个子节点的链接,而无需先检索所有子节点。

这种方法也有一些缺点。如果父级可能的子级数量超过几百个,或者根本不受限制,那么当数组变大时,将会对性能产生严重影响。 MongoDB特别推荐给Avoid Unbounded Arrays

在每个子项中存储父 ID 可以维护一个链接,而无需单个字段,该字段不需要是数组。这意味着获取给定父级的子级列表需要单独的查询或$lookup,但会简化先查找子级,然后链接到父级的过程。
这种方法完全避免了大数组的问题,即使未来数据集呈指数增长。

【讨论】:

  • 我们不希望每个父母有很多孩子,但是父母和孩子的总数可能很大,我们经常需要检索给定父母的所有孩子的列表。 $lookup 本身与通过父 ID 查找并从存储的子 ID 列表中填充相比如何?
  • 如果“填充”是指猫鼬填充方法,该方法在客户端处理,并将在子集合中为每个孩子使用单独的查找。使用 $lookup 可以在一次往返中获取文档,是否需要对子集合进行超过 1 个查询取决于管道的结构。如果您将父 ID 存储在子文档中,您可以找到 2 找到的所有数据 - 一个用于父级,一个用于子级。
  • 那么按 _id 搜索本质上没有什么比按任何其他字段搜索更快?
猜你喜欢
  • 2017-03-06
  • 1970-01-01
  • 2018-08-16
  • 2018-01-04
  • 1970-01-01
  • 2015-07-29
  • 2020-05-19
  • 1970-01-01
  • 2013-12-28
相关资源
最近更新 更多