gpt4 book ai didi

mongodb - 在 Mongo 中存储嵌套类别(或分层数据)的最有效方法?

转载 作者:IT老高 更新时间:2023-10-28 13:13:35 27 4
gpt4 key购买 nike

我们为多个产品(例如,体育 -> 篮球 -> 男装体育 -> 网球 -> 女装)嵌套了类别,并且使用 Mongo 而不是 MySQL .

我们知道如何在 MySQL 等 SQL 数据库中存储嵌套类别,但如果您能就如何为 Mongo 提供任何建议,我们将不胜感激。我们需要优化的操作是快速找到一个类别或子类别中的所有产品,这些产品可以嵌套在一个根类别之下的几层(例如,Men's Basketball 类别中的所有产品或女子网球类别)。

This Mongo doc建议了一种方法,但它表示当我们需要对子树进行操作时它效果不佳(因为类别可以达到多个级别)。

关于有效存储和搜索任意深度嵌套类别的最佳方法有什么建议吗?

最佳答案

您首先要决定的是您将使用哪种树。

要考虑的最重要的事情是您的数据和访问模式。您已经说过,您所有工作的 90% 都将是查询,并且听起来(电子商务)更新只会由管理员运行,而且很可能很少。

因此,您需要一个模式,让您能够通过路径快速查询 child ,即:体育 -> 篮球 -> 男子、体育 -> 网球 -> 女子,并且不需要真正扩展到更新。

正如您正确指出的那样,MongoDB 确实为此提供了一个很好的文档页面:https://docs.mongodb.com/manual/applications/data-models-tree-structures/从而 10gen 实际上为树陈述了不同的模型和模式方法,并描述了它们的主要起伏。

如果您希望轻松查询,应该引起注意的是具体化路径:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

这是一种非常有趣的构建树的方法,因为要在上面给出的示例中查询“网球”中的“女性”,您可以简单地执行一个预先固定的正则表达式(可以使用索引:http://docs.mongodb.org/manual/reference/operator/regex/)像这样:

db.products.find({category: /^Sports,Tennis,Womens[,]/})

查找树的特定路径下列出的所有产品。

不幸的是,这种模型在更新方面确实很糟糕,如果您移动一个类别或更改其名称,您必须更新所有产品,并且一个类别下可能有数千种产品。

更好的方法是在产品上放置一个 cat_id,然后使用架构将类别分成单独的集合:

{
_id: ObjectId(),
name: 'Women\'s',
path: 'Sports,Tennis,Womens',
normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}

所以现在您的查询只涉及类别集合,这应该会使它们更小且性能更高。异常(exception)情况是当您删除一个类别时,产品仍需要触摸。

所以一个把“网球”改成“羽毛球”的例子:

db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
doc.path = doc.path.replace(/,Tennis/, ",Badmin");
db.categories.save(doc);
});

不幸的是,MongoDB 目前不提供查询内文档反射,因此您必须将它们拉出客户端,这有点烦人,但希望它不会导致带回太多类别。

这基本上就是它真正的工作方式。更新有点痛苦,但我相信能够使用索引在任何路径上即时查询的能力更适合您的场景。

当然,额外的好处是此模式与嵌套集模型兼容:http://en.wikipedia.org/wiki/Nested_set_model我一次又一次地发现这对于电子商务网站来说非常棒,例如,网球可能同时属于“体育”和“休闲”,并且您需要多个路径,具体取决于用户来自哪里。

物化路径的架构很容易支持这一点,只需添加另一个 path,就这么简单。

希望它是有道理的,那里很长。

关于mongodb - 在 Mongo 中存储嵌套类别(或分层数据)的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14966777/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com