Rails自引用层次关系 [英] Rails self-referential hierarchical relationship

查看:159
本文介绍了Rails自引用层次关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了Rails指南,并尝试了一些带有Active Record的东西,但是还没有弄清楚实现此目的的最佳方法是什么.

I've read Rails guides and tried a few different things w/Active Record but haven't been able to figure out what the best way to do this is.

我需要建立一个分层的自引用(用户到用户)关系.通常,它的高度不超过5个级别,但应该可以无限扩大.

I need to set up a self-referential (users to users) relationship that is hierarchical. It usually would be no more than 5 levels high, but should be able to scale up infinitely.

我尝试用这样的数据库模式创建UserHierarchy模型:

I've tried creating a UserHierarchy model with a DB schema like this:

parent | child | level

但是,管理起来有点困难,太复杂了.

However, managing this is a bit too difficult and too complicated to handle.

在Rails中建立自引用层次关系的最佳方法是什么?我已经检查了祖先之类的宝石,但是其中大多数使用类继承,并且对于自引用关系而言效果不佳.这是一个多对多的自引用层次结构(在MySQL中).

What's the best way in Rails to do a self-referential hierarchical relationship? I've checked out gems like ancestry, but the majority of them use class inheritance and don't work well for self-referential relationships. It's a many-to-many, self-referential hierarchy (in MySQL).

推荐答案

祖先是esp的瑰宝之一.非常适合对象树结构(您称为自引用层次关系).您应该对此有更详细的了解.

Ancestry is one of the gems that is esp. well suited for object tree structures (what you call self-referential hierarchical relationships). You should have a more detailed look at it.

通常,有大约四种常见的方式将树存储在SQL数据库中:

Generally, there are about four common ways to store trees in a SQL database:

  • 简单的父指针.您只需向模型中添加一个名为parent_id的新列,即可保存父对象的ID.这样可以轻松插入,并且非常适合单级层次结构,但是通常很难用于更深层次的层次结构,因此通常不用作主要机制(尽管有时会与其他机制结合使用)
  • 嵌套集.您将树定义为结构套套.通常使用rightleft列来实现,这些列填充有数字以定义集合.它允许有效的查询,但是在插入值时有些棘手. Esp.当同时对树进行更改时,有时会出现不一致的情况.该模型例如习惯了 awesome_nested_set 宝石.
  • 材料化路径.这是模型,例如由祖先使用.它存储所有元素的完整父路径.这允许有效的插入和查询.换一棵树要贵一些.
  • 关闭树 .此机制将每个元素的所有父元素存储在一个表中.这是例如由 closure_tree 宝石使用.
  • Simple parent pointers. You just add a new column called parent_id to your model holding the ID of the parent object. This allows easy inserts and is well suited for single-level hierarchies but is generally difficult to use for deeper hierarchies and is thus generally not used as the primary mechanism (although it is sometimes combined with other mechanisms)
  • Nested Sets. You define your trees as a structure of nested sets. This is typically implemented with a right and a left column which are populated with numbers to define the set. It allows efficient querying but is a bit tricky when inserting values. Esp. when having concurrent changes to a tree, it is sometimes prone to inconsistencies. This model is e.g. used to the awesome_nested_set gem.
  • Materialized Paths. This is the model e.g. used by ancestry. It stores the full parent path of all elements. This allows for efficient inserting and querying. Changing a tree is bit more expensive.
  • Closure Trees. This mechanism stores for each element all of its parents in a table. This is e.g. used by the closure_tree gem.

通常,所有这些选项都允许存储对象树,即同一类对象的分层结构(在这种情况下为ActiveRecord模型).

Generally, all these options allow to store a tree of objects, i.e. a hierarchical structure of objects of the same class (an ActiveRecord model in this case).

使用哪种取决于特定的使用案例,哪些折衷方案更为重要.最重要的是,您应该弄清楚您是否经常更改树(例如,移动子树或仅添加叶子)以及如何查询树(例如,您是否仅需要直子,是否需要整个子树,您需要进行过滤),然后基于此选择合适的解决方案.

Which one to use depends on which trade-offs are more important for your specific use-case. Most importantly, you should figure out if you are changing trees often (e.g. moving sub-trees around or adding only leaves) and how you are querying the tree (e.g. do you only need direct children, do you need whole sub-trees, do you need to filter) and chose the appropriate solution based on that.

这篇关于Rails自引用层次关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆