【问题标题】:What is the correct way of creating a document that can be queried by any of its elements?创建可以通过其任何元素查询的文档的正确方法是什么?
【发布时间】:2018-05-30 15:30:26
【问题描述】:

我正在做一个项目,我希望通过搜索池中的任何元素来返回“池”中的所有文档。

例如,假设我们有 3 个池,每个池都有不同的用字母标记的文档

池 1:A, B, C

池 2:D

池 3:E, F, G, H

当我搜索A 时,我想得到ABC。当我搜索C 时,我还想得到ABC

如果我添加了一个文档I,并且它满足池 1 和 2 的条件,那么池 1 和 2 应该被合并,并且任何对任何 A, B, C, D, I 的搜索都应该返回所有这些。

我知道如何低效地执行此操作(以每个元素为键创建一个新文档,然后在每次插入时更新所有文档),但我想知道是否有更好的方法?

提前致谢

【问题讨论】:

  • 你看过indexing吗?
  • 或者考虑重写查询以查看文档中的元素,而不是只查看键?
  • 或者修改文档/集合设计以便查询方便?
  • 或以上方法的组合?

标签: database mongodb mongoose mongodb-query


【解决方案1】:

我认为对于像数据这样抽象的东西,尤其是数据库文档,良好的可视化有助于概念化问题。尝试从试图维护一组深度不超过 1 的树的角度来看待这个问题。具体来说,每个文档都是一个叶子,而确定哪些是“池”的一部分的“规则”是根(即根是标签的子集,可以是叶子)。

现在,你说你想做的是能够添加一个新的叶子。如果这个叶子能够连接到多个根,那么这些根应该被合并,这意味着更新根是什么并将受影响树中的每一片叶子指向这个新根。

否则,您最终需要从新叶子跳到它连接的每个根,然后再跳到其他每个叶子。但每一片叶子也可能与其他根相连,这意味着你可以像这样跳来跳去任意次数。这是一个不理想的情况。

为了让这个查询高效,您需要决定这些“根”将是什么并相应地更新它们。例如,您可能决定保留一个“池”文档并根据需要将这些“池”合并在一起,例如通过拥有一个 labels 字段,该字段是要包含在池中的标签数组。合并只是合并数组本身的问题。或者,您可以使用通用 ObjectId(不一定附加到任何特定文档)并将此值用作一种“伪根节点”来代替文档。您可以探索许多选项。但是,一般来说,您应该尽量减少对单个文档的字段值的检查,减少为单个值检查(例如,不要在每个文档中保留其他“相关”标签的数组!)。

无论您采用何种方法,请牢记这些树结构,考虑在 MongoDB 查询方面遍历节点意味着什么,并确定您希望如何遍历节点,以便 1) 确保“跳数” " 您需要在节点之间进行恒定时间操作,并且 2) 确保您可以高效可靠地合并这些根,而不会有数据丢失的风险。

最后,如果您发现更新查询太慢,那么您可能遇到了索引问题。使用适当的索引,更新包含数百万个文档的集合根本不需要任何时间。此外,如果您没有进行multi 更新,而是为每个文档运行单独的更新,那么您的更新写得不好,因为您将遇到O(n) 搜索时间和网络开销,这会减慢您的更新到爬行。

【讨论】:

    猜你喜欢
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多