以 N 级菜单为例,在 php 下我是这样的:
`先用 "select * from trees" 查询出所有的菜单项,存入到一个数组,然后用一个递归函数循环这个数组,遇到 tree1.id == tree2.parent_id 的时候,把 tree2 保存到 tree1 的 children 里面。
这样只运行了一行 sql 查询,剩下的用程序算法实现。
在 ruby 下我也试着这样处理,结果速度慢的超乎我的想想,于是,在 ruby 下我只能这样做:
先用 "select * from trees where depth=1" 查询出所有的一级菜单项,然后
trees = trees.map do |tree|
tree.children = Tree.where(parent_id: tree.id)
tree.children = tree.children.map do |child|
child.children = Tree.where(parent_id. child.id)
child
end
tree
end
这样会进行好多次 sql 查询,但这样的速度是最快的,对 ruby 来说
================================= 2015-04-27 20:06 补充 ================================== PHP 递归实现菜单树的代码:
function make_tree($arr){
if(!function_exists('make_tree1')){
function make_tree1(&$arr, $parent_id=0){
$new_arr = [];
foreach($arr as $k=>$v){
if($v->parent_id == $parent_id){
$new_arr[] = $v;
unset($arr[$k]);
}
}
foreach($new_arr as &$a){
$a->children = make_tree1($arr, $a->id);
}
return $new_arr;
}
}
return make_tree1($arr);
}
那一定是你的用法不对,不要随便下结论,尤其是你不了解一个东西的时候。 贴你在 PHP 里面的 SQL 和完整代码,以及同样的方式,你在 Ruby 里面是如何写的
感觉可以类似这类的重新设计下:
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee",
foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
可能不是语言层面,而是 ORM 层面吧,不知道 LZ 对 ActiveRecord 熟吗?
我猜测慢的原因大致是 遇到 tree1.id == tree2.parent_id 的时候
当然只是我的猜测
针对实际问题而谈的话,无限极分类问题可以参考这个 gems https://github.com/stefankroes/ancestry 感觉既然选择一门语言的话,应该关注它的长处并加以利用,ruby 这个环境下本身就有着各式各样的轮子,既然选择了 ruby 也说明是需要敏捷开发的, 这样的话放着现成的东西不去用,自己纠结怎么能写出效率还可以的代码不是适得其反么。
我也发现 ruby 比 php 慢好多 比如我要计算 10000 个用户,每个人手里有 10000 本书,以前我用 PHP 的时候 都是用这个方法得到书的总数:
$book_count = 10000 * 10000;
可是用了 ruby 之后,我发现我是这么写代码的
book_count = 0;
10000.times do |people|
10000.times do |book|
book_count = book_count +1
end
end
一执行起来,ruby 真的好慢好慢 所以我认为 ruby 好慢,大家说呢?
顺带提一下,Ruby 里面正确解决 Nested Set 的场景可以用这个东西来完美处理:
➜ time php test.php php test.php 0.07s user 0.01s system 97% cpu 0.083 total ➜ time ruby test.rb ruby test.rb 5.30s user 0.05s system 99% cpu 5.352 total
果然还是 php 厉害!!!
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
N+1 问题,你在 rails 里面这样操作和 php 比是没得比的,你的设计和用法有问题
Ruby on Rails 在运行速度或性能上对其他语言少有优势。大家选择它是因为开发速度快。经常看到有人说,你用 Ruby on Rails 做出产品来,当你的用户足够多,以至于 Rails 成为瓶颈时,你肯定有足够的资源找人用性能更好的语言改写。
time 一下这个吧... 其实楼主你的 ruby 代码和 php 代码都写复杂了
trees = trees.to_a
q = trees.group_by &:parent_id
trees.each do |t|
t.children = q[t.parent_id]
end
#35 楼 @luikore 这样得出来的 tree 是这样的,用 json 表示吧:
[{
name: 一级分类
children: [
{
name: 二级分类1
}
]
},
{
name: 二级分类1
children: [
{
name: 三级分类1
},
{
name: 三级分类2
}
},
{
name: 三级分类1
children: []
},
{
name: 三级分类2
children: []
}]
我需要的是这样的
[{
name: 一级分类
children: [
{
name: 二级分类1
children: [
{
name: 三级分类1
children: []
},
{
name: 三级分类2
children: []
}
}
]
}]
trees = trees.to_a
q = trees.group_by &:parent_id
trees.each do |t|
t.children = q[t.id]
end
# 如果要选取根节点, trees.select!{|t| !t.parent_id}