【问题标题】:How can I search a subset of a tree efficiently in mongo?如何在 mongo 中有效地搜索树的子集?
【发布时间】:2015-01-31 07:00:39
【问题描述】:

我在 Mongo 数据库集合中有数据,其中每个文档都有父级的 id。如果我想搜索在其祖先中具有特定文档(我将其称为 P)的所有文档(即 P 是它的父母、祖父母、曾祖父母等),我有什么选择可以有效地做到这一点,并且这些选项的优缺点是什么?

我能想到以下几点:

  • 将整个祖先存储在每个文档中,这样您就可以搜索祖先列表中包含 P 的文档。
    • 优势:
      • 恒定时间查找
    • 缺点:
      • 如果更改了父级,则相应的更新为 O(n),其中 n 是更改了父级的文档的后代数
      • 一些存储开销,O(a),其中 a 是文档的平均深度
  • 搜索时,首先建立一个P的子文档的id列表,然后是孙文档等。然后搜索所有具有这些id的文档
    • 优势:
      • 无需更改存储结构,无需额外的空间开销
    • 缺点:
      • 建立 id 列表是一个 O(n) 操作,其中 n 是 P 的后代文档数
      • 按可能数百个 ID 进行搜索可能效率不高

有人知道其他技术吗?

【问题讨论】:

  • 我没有,但它是一个非常相关的参考。看起来“祖先数组”和“物化路径”本质上是一样的,都是我在那里的第一个选择。嵌套集对我来说不是一个选项,另外两个基本上是我已经在做的

标签: mongodb search indexing tree


【解决方案1】:

规范化或不规范化;我相信这就是经常让人们转向 SQL /RDBMS 的 NoSQL 的弱点。我不喜欢规范化,以便通过基本的后端和前端代码提供近乎实时的索引简单查询。这是related question 中的一些伪代码,显示了规范化时所需的复杂代码。在 NoSQL 中很难模拟连接和关系。

Granted NoSQL 确实打开了一个真正的老鼠窝,例如您的“如果更改了父级,则相应的更新是 O(n),其中 n 是父级更改的文档的后代数”我称之为“关系维护脚本”。但我发现您可以在非工作时间按计划(crontab)运行这些。人们也可能会强烈考虑安全表/集合并构建易失性或工作表。有关 OLAP 表,请参阅 this question。在那里,您可以将您的关系放在漂亮整洁的表格中,然后创建那些丑陋的快速集合。

这是一个确定 NoSQL 是否真的适合您的问题。即使在个人层面上,您更喜欢更快、可扩展和混乱 - 还是更慢、不可扩展和整洁/有条理。类似于经典的快速、好和便宜的三角形的权衡。基本上,NoSQL 又快又便宜; SQL 很好。 NoSQL 的优点是可扩展性;而 SQL 的速度实际上是值得尊敬的。

【讨论】:

  • 嗯,所以实际上我认为您在关系数据库中会遇到完全相同的问题。加入或不加入,一棵树也不容易在 SQL 中表示。仅当您对基本损坏的数据感到满意时,才可以脱机运行“关系维护脚本”。这对我不起作用。我不是很清楚你在建议或推荐什么。您提供的链接似乎与我的问题密切相关。
  • 我建议您执行选项 1。可以为树执行单个(但复杂的)sql 语句,但使用 nosql 这是不可能的。因此,要么构建数据以适应单个查询,要么创建一个非常复杂且缓慢的 map/reduce 或后端。对我来说,它快速而丑陋的数据和干净的专有代码。你也可以看看 neo4j 或类似的图 nosql,也许它们会提供一个很好的平衡 b/w 速度和丑陋的数据结构。
  • 我猜想这种递归查询在 mysql 之类的东西中是不可能的,但在其他系统中是不可能的。所以我可以接受多个查询,这使得它尽可能像在 sql 中一样,并且基本上也具有可扩展性。为了更快地做到这一点,即使在带有递归查询的 SQL 中,我认为您必须构建相同的混乱数据。不过谢谢。
猜你喜欢
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 2012-03-25
  • 2012-07-30
  • 2019-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多