我有一個與地理有關的類的集合:State,Msa,County,City等。這些類都從基地Location類下降。這些類大部分都是通過名爲geography的非規範化連接表相關的。所以,我有...與下面的關聯:uniq => true並不總是返回唯一的結果
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會得到1000個結果(地理表又是一種數據集市,這就是爲什麼我在關聯中使用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個,然後在紅寶石,砍伐的結果向不同組的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
我的問題是:
- 爲什麼沒有在它從查找調用產生的查詢中使用DISTINCT Rails的?我猜這是因爲我要求它:include =>:states。我應該使用:連接嗎?
- 爲什麼Rails在調用msas.first.states時返回非唯一結果?不應該有一個:uniq => true的協會強制執行結果的唯一性?
- 爲什麼我需要使用Rails用於位置表狀態「版本」的表別名,即:conditions => {:states_locations => {:id => 1}}? Rails似乎並不理解:include =>:states,:conditions => {:states => {:id => 1}}。有沒有辦法確定性地預測表別名?
任何見解將不勝感激。
在此先感謝,傑森
喬納森您好,感謝您的答覆。我嘗試過使用:select選項,但是,我發現:使用include時會忽略select。另外,爲了清楚起見,您引用的第二行代碼*是*在Ruby中返回唯一結果*,而不是在SQL中。我會看看喬希的帖子,看看它是否提供了進一步的見解。再次感謝。 – Jason 2010-01-28 15:30:34
Josh的帖子證實Rails確實使用Ruby而不是SQL來在has_many:through => xxx,:uniq => true關聯中「唯一」。但是,它沒有提供爲什麼msas.first.states返回非唯一結果的洞察。人們會認爲,由於Rails足夠聰明,可以獨特地使用原始結果集(儘管在Ruby中),但它也足夠聰明,可以獨立於結果集中對象的關聯。也許我需要深入瞭解Rails中的關聯代碼。 – Jason 2010-01-28 15:53:26