Arel 刚刚发生了什么?我该如何处理 Arel::SelectManager?
我拼命地试图理解 Arel,主要是因为我讨厌处理 SQL;我做得很好,但我碰壁了。
我一直在 Rails 3.0.0 中工作,我正在尝试使用一些数学知识进行复杂的查询。实际情况要复杂得多,但我简化了一些。在我的示例中,我有一个包含特定字符串字段的表,我想要所有记录的计数,以及该字段的两个可能值中每一个的计数,按外部 ID 分组。
在 Rails 3.0.0 下,我可以这样做(控制台命令):
t = Arel::Table.new(:some_thingies)
e = t .project(t[:foreign_id], t[:foreign_id].count.as('all_count')) .group(t[:foreign_id])
c = t.where(t[:some_field].eq('type1')).project(t[:foreign_id], t[:foreign_id].count.as('type1_count')).group(t[:foreign_id])
x = e
x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
此时我可以执行 x.to_sql 并且...好吧,我不完全确定它是正确的,但结果看起来是正确的,除了foreign_id 列两次。
SELECT
`some_thingies_external`.`foreign_id`,
`some_thingies_external`.`all_count`,
`some_thingies_external_2`.`foreign_id`,
`some_thingies_external_2`.`type1_count`
FROM
(SELECT
`some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1+count`
FROM `some_thingies`
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external`
INNER JOIN
(SELECT `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1_count`
FROM `some_thingies`
WHERE `some_thingies`.`type` = 'type1'
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external_2`
ON `some_thingies_external`.`foreign_id` = `some_thingies_external_2`.`foreign_id`
到目前为止,一切都很好。然而,当我尝试加入第二组这样的计数时:
i = t.where(t[:some_field].eq('type2')).project(t[:foreign_id], t[:foreign_id].count.as('type2_count')).group(t[:foreign_id])
x = x.join(i).on(e[:foreign_id].eq(i[:foreign_id]))
它只是挂断,导致我认为我正在点击 这个错误
(顺便说一句,我有更多的计数要添加,理想情况下,“some_thingies”本身应该是一个 arel 对象,表示对我们正在计数的事物进行更多过滤。 。但我离题了......)
所以,我决定尝试最新的边缘 Arel 和 Rails,并相应地提高了我的宝石:
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
gem 'arel', :git => 'http://github.com/brynary/arel.git'
现在,当我尝试进行 first 连接时,它失败了悲惨地:
ruby-1.9.2-preview3 > x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
NoMethodError: undefined method `[]' for #<Arel::SelectManager:0x00000104311e38>
from (irb):12
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:44:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:8:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands.rb:33:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
这看起来不像是 Arel 中的错误 - 如果有的话,看起来更像是它之前工作过的事实就是错误。我想我只是不知道 Arel::SelectManager 是什么以及如何使用它。看起来我做得很好,但我真的不明白发生了什么。
我是否需要以某种方式根据我拥有的 SelectManager 创建一个新表?或者我的配置中做错了什么导致 [] 语法失败?或者我完全不明白阿雷尔的所作所为?我仍然不太明白我应该用 Arel::Rows 做什么,但我想我会掌握它的窍门;我怀疑我可以通过项目()摆脱结果中额外的外键......
但我仍然很迷失。哈哈哈!
另外,“railties”与“frailties”或“mail girls”押韵吗?
I'm desperately trying to make sense of Arel, mostly because I hate dealing with SQL; I was doing so well, but I've hit a wall.
I've been working in Rails 3.0.0, and I'm trying to make a complex query with some math in it. The real case is rather more complex, but I've simplified a bit. In my example, I have a table with a particular string field, and I want a count of all the records, as well as a count for each of two possible values of that field, grouped by a foreign id.
Under Rails 3.0.0, I can do this (console commands):
t = Arel::Table.new(:some_thingies)
e = t .project(t[:foreign_id], t[:foreign_id].count.as('all_count')) .group(t[:foreign_id])
c = t.where(t[:some_field].eq('type1')).project(t[:foreign_id], t[:foreign_id].count.as('type1_count')).group(t[:foreign_id])
x = e
x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
and at this point I can do do x.to_sql and... well, I'm not entirely sure it's right, but the results look right, aside from having the foreign_id column twice.
SELECT
`some_thingies_external`.`foreign_id`,
`some_thingies_external`.`all_count`,
`some_thingies_external_2`.`foreign_id`,
`some_thingies_external_2`.`type1_count`
FROM
(SELECT
`some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1+count`
FROM `some_thingies`
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external`
INNER JOIN
(SELECT `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1_count`
FROM `some_thingies`
WHERE `some_thingies`.`type` = 'type1'
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external_2`
ON `some_thingies_external`.`foreign_id` = `some_thingies_external_2`.`foreign_id`
So far so good. However, when I try to join in a second set of counts like this:
i = t.where(t[:some_field].eq('type2')).project(t[:foreign_id], t[:foreign_id].count.as('type2_count')).group(t[:foreign_id])
x = x.join(i).on(e[:foreign_id].eq(i[:foreign_id]))
it just hangs up, leading me to think I'm hitting this bug
(btw I've got more counts to add in, and ideally 'some_thingies' should itself be an arel object representing more filtering on which thingies we're counting... but I digress...)
So, I decided to try out the latest edge Arel and Rails, and bumped up my gems accordingly:
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
gem 'arel', :git => 'http://github.com/brynary/arel.git'
and now when I try to do do the first join, it fails miserably:
ruby-1.9.2-preview3 > x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
NoMethodError: undefined method `[]' for #<Arel::SelectManager:0x00000104311e38>
from (irb):12
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:44:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:8:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands.rb:33:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
This doesn't seem like a bug in Arel - if anything, it seems more like the fact that it worked before is the bug. I think I just don't know what an Arel::SelectManager is and what to do with it. It seemed like I was doing so well, but I really don't get what is going on.
Do I need to somehow make a new table based on the SelectManager I've got? Or am doing something wrong in my configuration which makes the [] syntax fail? Or do I just totally fail to understand what Arel does? I still don't quite get what I'm supposed to do with Arel::Rows, but I suppose I'll get the hang of that; and I suspect I can get rid of the extra foreign key in the results with a project()...
But I'm still pretty lost. Haaaaalp!
p.s. does 'railties' rhyme with 'frailties,' or with 'mail guys'?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我要回答我自己的问题,因为似乎没有人感兴趣,现在我知道我做错了什么,我可以看到如果我理解 SQL,这将是显而易见的。
我使用 Arel 的方式的问题 1 是你只能加入一张新制作的桌子。那不是重点。
真正的问题是我正在尝试计算两个不同的东西。我真的应该按外部 ID 和“some_field”进行分组。我只是不知道你能做到这一点,而且结果有点奇怪。如果我不关心 some_field 的所有可能值,这可能会很烦人,但我确实关心它们,并且我可以轻松地将它们相加以获得总数,并且现在很容易将它们过滤掉。
一旦我弄清楚了这一点,我就知道如何使用普通的 ActiveRecord 而无需 ARel 来做到这一点:
天啊!寓意:SQL 只知道行。时期。
I'm going to answer my own question, since no one seems interested, and now that I know what I'm doing wrong, I can see it would be obvious if I understood SQL.
Problem 1 with the way I was using Arel is you can only join a freshly-made table. That's beside the point.
The real problem is I'm trying to count two different things. I really should be grouping by the foreign ID AND the 'some_field'. I just didn't know you could do that, and the results from it are a little weird. If I didn't care about all the possible values of some_field, this might be annoying, but I do care about them all, and I can add them up easily enough to get the total, and it's easy to filter them out now.
Once I figured that out, I figured out how to do it with normal ActiveRecord and no ARel:
D'oh! Moral: SQL only knows about rows. Period.
Arel 已从内脏上彻底重做。该倡议由enderlove (Aaron)发起,在大部分组合查询上存在性能问题。
我自己也为这项新举措做出了贡献。
Arel 现在使用抽象语法树(在选择管理器内)和访问者模式。
您不妨放弃 Arel 1.0.1 在 2.0.0 中的工作方式(在升级到 3.0.x 的过程中以与 Rails 保持一致)
Arel has been completely redone from the guts up. This initiative was started by tenderlove (Aaron)There were performance problems problems on largely composed queries.
I have even made contributions to this new initiative myself.
Arel now uses the Abstract Syntax Tree (within Select Manager) and the Visitor Pattern.
You might as well scrap the way that Arel 1.0.1 works in flavor for 2.0.0 (on the way to 3.0.x to align with rails)