Что только что случилось с Arel и что мне делать с Arel :: SelectManager? - PullRequest
5 голосов
/ 15 октября 2010

Я отчаянно пытаюсь понять Арела, в основном потому, что я ненавижу иметь дело с SQL;У меня все хорошо, но я попал в стену.

Я работаю в Rails 3.0.0 и пытаюсь сделать сложный запрос с какой-то математикой.Реальный случай довольно сложен, но я немного упростил.В моем примере у меня есть таблица с определенным строковым полем, и я хочу подсчет всех записей, а также подсчет для каждого из двух возможных значений этого поля, сгруппированных по внешнему идентификатору.

В 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 и 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'

, и теперь, когда я пытаюсь сделать первое соединение, онос треском проваливается:

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, но, полагаю, я пойму это;и я подозреваю, что могу избавиться от лишнего внешнего ключа в результатах проекта () ...

Но я все еще довольно растерян.Хааааальп!

ps рифмуется с "хрупкостью" или с "почтовыми парнями"?

Ответы [ 2 ]

3 голосов
/ 04 ноября 2010

Арел был полностью переделан изнутри. Эта инициатива была инициирована Tenderlove (Аарон). Были проблемы с производительностью в основном составленных запросов.

Я даже сам внес свой вклад в эту новую инициативу.

Арель теперь использует Абстрактное синтаксическое дерево (в Select Manager) и Шаблон посетителя.

Вы могли бы также отказаться от того, как Arel 1.0.1 работает с ароматом для 2.0.0 (на пути к 3.0.x для выравнивания с рельсами)

3 голосов
/ 16 октября 2010

Я собираюсь ответить на свой собственный вопрос, поскольку никто не заинтересован, и теперь, когда я знаю, что я делаю неправильно, я вижу, что было бы очевидно, если бы я понимал SQL.1 с тем, как я использовал Arel, вы можете присоединиться только к свежеприготовленному столу.Это не относится к делу.

Настоящая проблема в том, что я пытаюсь сосчитать две разные вещи.Я действительно должен группировать по внешнему идентификатору И 'some_field'.Я просто не знал, что ты можешь сделать это, и результаты от этого немного странные.Если меня не волнуют все возможные значения some_field, это может раздражать, но я забочусь обо всех них, и я могу сложить их достаточно легко, чтобы получить общее значение, и теперь их легко отфильтровать.

t = Arel::Table.new(:some_thingies)    
e = t.group(:foreign_id, :some_field).project(t[:id], t[:foreign_id], t[:some_field])

Как только я понял это, я понял, как это сделать с обычным ActiveRecord и без ARel:

SomeThing.group('foreign_id, some_field').select('id, foreign_id, some_field, count(1)')

D'oh!Мораль: SQL знает только о строках.Период.

...