草庐IT

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

coder 2023-05-04 原文

我们为多个产品(例如,体育 -> 篮球 -> 男装体育 -> 网球 -> 女装)嵌套了类别,并且使用 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/

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

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  9. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  10. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

随机推荐