Ruby on rails Rails:单个项目的多个树

Ruby on rails Rails:单个项目的多个树,ruby-on-rails,tree,hierarchy,nested-sets,Ruby On Rails,Tree,Hierarchy,Nested Sets,我想对多棵树中的对象进行分类,以反映它们的特征,并在此基础上构建导航 因此,考虑到以下树木: Category1 -Category-1-1 -Category-1-2 Category2 -Category-2-1 -Category-2-2 --Category-2-2-1 例如,对象可以同时属于类别-1-2和类别-2-2-1 目标是能够从数据库中获取所有对象 属于某一类别的 属于某一类别或其下属的 一个更实际的例子: 类别可能具有“工具>园艺工具>刀具”的层次结构 第二类:“硬对象

我想对多棵树中的对象进行分类,以反映它们的特征,并在此基础上构建导航

因此,考虑到以下树木:

Category1
-Category-1-1
-Category-1-2

Category2
-Category-2-1
-Category-2-2
--Category-2-2-1
例如,对象可以同时属于类别-1-2和类别-2-2-1

目标是能够从数据库中获取所有对象

  • 属于某一类别的
  • 属于某一类别或其下属的
一个更实际的例子:

类别可能具有“工具>园艺工具>刀具”的层次结构

第二类:“硬对象>金属对象>小金属对象”

对象“修剪器”将被分类为属于“刀具”以及“小金属对象”

我希望能够

  • 检索所有“园艺工具”->“修剪器”
  • 检索“园艺工具”->“刀具”的所有类别子项
  • 检索所有“硬对象”->“修剪器”
  • 检索所有同时也是“切割器”->“修剪器”的“硬对象”
  • 检索所有同时也是“切割器”的“软对象”->[] 有什么建议吗?我简单地看了一下闭包树、很棒的嵌套集合等等,但我不确定它们是否是一个很好的匹配

我想你可以买一颗我个人喜欢的树宝石。然后为每个类别建立关联,使其具有多个对象,并且每个对象可以属于多个类别

您是否已经遇到任何问题,或者只是在研究您的选项?

请注意,这里的代码都是伪代码

我将使用gem,并使用三个模型类对数据进行建模。 通过这种方式,您的数据被规范化,这是一个很好的基础

Category - ancestry tree
  has_may Memberships
  has_may Products through Memberships

Membership
  belongs_to Category
  belongs_to Products

Products
  has_may Memberships
  has_may Categories through Memberships
从那时起,您需要弄清楚如何高效地执行这些等式。 我这样做的方法是了解如何使用SQL,然后找出如何使用activercord的DSL表达查询

一些资源:

  • 这本书有一些复杂SQL查询的例子,这些查询被转换成可重用的作用域和帮助器
  • Rails的文档,请参阅连接和包含部分
  • SQL连接的一个很好的解释
查询示例:

找到一个类别

Category.find(Category\u id)

查找类别并将其产品包含在指定类别内

Category.find(Category\u id).join(:memberships=>:products)

查找类别的子树ind include products

Category.subtree\u of(Category\u id).join(:memberships=>:products)

查找产品所属的所有类别


Product.find(Product\u id).categories

我只是这样做了,我选择不使用祖先,但因为作者说它更快,我同意他的观点。要知道,在类别(每当我向一个对象添加多个标记时,我喜欢称之为标记)和对象之间需要一个“has_和_belient_to_many”

现在,对于查找者来说,坏消息是,如果没有自己的自定义查询,您可能无法使用一个。使用gems方法,您将执行以下操作:

Item.joins(:tags).where(tags: {id: self_and_descendant_ids })
代码是干净的,它执行两个查询,一个用于子体ID,另一个用于对象。这方面稍有变化,除了最后一个,应该能满足你的所有需求。这是一个艰难的,我还没有实现它(我在这个过程中)

现在,您必须对这两个(查询计数:2)、这些标记中的所有项(查询计数:4)和相交调用
tag.self\u和\u祖先\u id
。在此之后,需要进行一些认真的重构。我认为我们需要编写SQL来减少查询的数量,我认为Rails查询接口是不够的


我选择*closure\u tree*的另一个原因是使用了parent\u id,所有的兄弟姐妹都共享它(就像任何其他Rails关联一样),因此它更容易与其他gem进行交互(例如RankedModel to sort)。

也许我误读了祖先的工作原理,但它不只是允许我将对象放在一个树中吗?是的,我要做的是以树状结构组织类别,然后将每个节点(类别)与您要分类的对象连接起来。我非常喜欢您的答案,但已将奖金授予其他用户,希望激励她/他成为SO的更积极的用户。不过,我接受你的回答。谢谢你的详尽回答。