递归加载层次结构中的所有子/父记录

发布于 2024-12-07 03:40:01 字数 1301 浏览 0 评论 0原文

-- Rails:2.3.8,Ruby:1.9.2v180,MySQL:5.1.56 --

我有一个名为ExternalCategory的递归模型

  belongs_to :parent, :class_name => "ExternalCategory", :foreign_key => "parent_id"

  has_many :children, :class_name => "ExternalCategory", :foreign_key => "parent_id"

我在分页视图中显示此层次结构,其中最初只有一些顶级类别可见。这些顶级类别的所有祖先都会加载到页面,但仅通过 js 显示。

一个ExternalCategory可能有超过1000个祖先,因此如果不急切加载这些页面可能会花费大量时间来加载。话虽这么说,我一直致力于以适当的方式添加急切加载,但我不太确定那会是什么。也许你能帮忙。

目前,我在ExternalCategory:内部有一个top_level_categories的范围,

named_scope :top_level_categories, :conditions => "parent_id is null"

然后附加到上面的has_many :children ...行的末尾,我添加了这个警告:

   , :include => :children

所以现在每当我加载任何ExternalCategory 的子级,这些子级的子级以及所有这些子级的子级都会被加载,依此类推。理想情况下,我不会在模型本身中执行此操作,而是在范围内执行此操作,但现在我可以接受这种糟糕的情况。

所有这一切的主要问题是我在表中构建行 id,这些行 id 引用当前元素的 id 及其所有祖先的 id。当展开/折叠任何类别的子视图时,js 会使用此 id。为了创建这些 id,我通过递归调用 #parent 来访问当前类别的祖先。我最终在日志中看到大量相同的行,如下所示:

CACHE (0.0ms) SELECT * FROM external_categories WHERE (external_categories.id = 216)

如果我避免为行提供所有唯一的 id,它会完全破坏页面(显然),但事情会开始加载 lickity split。

此时,任何建议、替代观点或您所拥有的都将不胜感激。

提前致谢!

-- Rails: 2.3.8, Ruby: 1.9.2v180, MySQL: 5.1.56 --

I have a recursive model called ExternalCategory which

  belongs_to :parent, :class_name => "ExternalCategory", :foreign_key => "parent_id"

and

  has_many :children, :class_name => "ExternalCategory", :foreign_key => "parent_id"

I display this hierarchy in a paginated view where only some number of top-level categories are initially visible. All ancestors of these top-level categories get loaded to the page but are only displayed via js.

An ExternalCategory may have over 1000 ancestors, so without eager loading these pages can take a huge amount of time to load. That being said, I've been working on adding eager loading in an appropriate fashion but I'm not quite sure what that would be. Perhaps you can help.

At the moment, I have a scope for the top_level_categories inside of ExternalCategory:

named_scope :top_level_categories, :conditions => "parent_id is null"

and then tacked on to the end of the has_many :children ... line up above I've added this caveat:

   , :include => :children

So now whenever I load the children of any ExternalCategory, the children of those children get loaded, along with the children of all those children, and so on. Ideally I wouldn't be doing this in the model itself but rather in the scope, but right now I'm okay with that bit of crappiness.

The main problem with all this is that I'm building up row ids in my table which reference the current element's id as well as all of it's ancestors' ids. This id gets used by the js when expanding/collapsing any category's children view. In order to create these ids, I access the current category's ancestors with recursive calls to #parent. What I end up with in my log is a ton of identical lines that look like this:

CACHE (0.0ms) SELECT * FROM external_categories WHERE (external_categories.id = 216)

If I avoid giving the rows all unique ids, it completely breaks the page (obviously), but things start loading lickity split.

Any advice, alternate perspectives or what have you would be immensely appreciated at this point.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱你不解释 2024-12-14 03:40:01

内置的 acts_as_tree 插件在这方面不太擅长,但还有像 ancestry 这样的替代品 支持 root_id 来解决这个特定问题。

不需要更改任何内容的方法涉及在下一个深度“级别”之后获取一个深度“级别”,直到用完结果为止,从而极大地缩短检索时间。

更好的方法是添加一个 root_id 列,这将使获取特定分支中的所有记录变得非常快。不过,您必须在迁移中计算该值才能正确应用它。不过,如果只执行一次,那么操作可能会很慢。

The built in acts_as_tree plugin is not very good at this, but there are alternatives like ancestry which support root_id to address this specific problem.

The approach that doesn't require changing anything involves fetching one "level" of depth after the next until you run out of results, trimming your retrieval time dramatically.

The better approach is to add a root_id column that will make fetching all of the records in a particular branch very fast. You will have to compute this value in your migration, though, to apply it correctly. That can be a slow operation if it is only done once, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文