У меня есть коллекция классов, связанных с географией: State, Msa, County, City и т. Д. Все классы происходят от базового класса Location. Классы связаны, по большей части, через денормализованную таблицу соединений, называемую географией. Итак, у меня есть ...
class Geography < ActiveRecord::Base
belongs_to :state
belongs_to :county
belongs_to :city
# ... etc.
end
class Location < ActiveRecord::Base
end
class State < Location
has_many :geographies
has_many :msas, :through => :geographies, :uniq => true
# ... etc.
end
class Msa < Location
has_many :geographies
has_many :states, :through => :geographies, :uniq => true
# ... etc.
end
Теперь, когда я запускаю из консоли следующее:
>> msas = Msa.find(:all, :include=>"states", :conditions=>{"states_locations"=>{"id"=>"1"}})
Я получаю правильное количество результатов (13 в данном случае). Однако, запустив SQL, который производит этот вызов find, я получаю тысячи результатов (опять же, географическая таблица - это своего рода datamart, поэтому я использую опцию: uniq для ассоциации).
SELECT `locations`.`id` AS t0_r0,
`locations`.`parent_id` AS t0_r1,
`locations`.`type` AS t0_r2,
`locations`.`name` AS t0_r3,
`states_locations`.`id` AS t1_r0,
`states_locations`.`parent_id` AS t1_r1,
`states_locations`.`type` AS t1_r2,
`states_locations`.`name` AS t1_r3
FROM `locations`
LEFT OUTER JOIN `geography`
ON `locations`.`id` = `geography`.`msa_id`
LEFT OUTER JOIN `locations` states_locations
ON `states_locations`.`id` = `geography`.`state_id`
AND `states_locations`.`type` = 'State'
WHERE `states_locations`.`id` = '1'
AND `locations`.`type` = 'Msa'
Я предполагаю, что это означает, что Rails загружает 1000 тысяч записей в память И ТОГДА в Ruby, сокращая результаты до отдельного набора Msas (в данном случае); кажется немного неэффективным. Кроме того, следующие последующие вызовы возвращают разные результаты:
>> msas.first.states.size # incorrect count
=> 192
>> msas.first.states.count # correct count
=> 1
>> msas.first.states # incorrect number of State objects
=> [#<State id: 1, ... >, ..., #<State id: 1, ... >]
>> msas.first.reload.states
=> [#<State id: 1, ... >] # correct number of State objects
Мои вопросы:
- Почему Rails не использует DISTINCT в запросе, который он генерирует из вызова find? Я предполагаю, что это потому, что я попросил: include =>: states. Должен ли я использовать: объединяет вместо?
- Почему Rails возвращает неуникальные результаты при вызове msas.first.states? Разве ассоциация, имеющая: uniq => true, не должна обеспечивать уникальность результатов?
- Почему мне нужно использовать псевдоним таблицы, который Rails использует для состояний "версия" таблицы местоположений, то есть: условие => {: states_locations => {: id => 1}}? Rails, похоже, не понимает: include =>: states,: condition => {: states => {: id => 1}}. Есть ли способ детерминированного прогнозирования псевдонима таблицы?
Любые идеи будут высоко оценены.
Заранее спасибо,
Jason