混合:选择:包含在查找方法中(Rails 2)

时间:2013-03-18 17:10:54

标签: ruby-on-rails ruby include find ruby-on-rails-2

我有2个模型,UserUserProfileuser has_one user_profile和user_profile belongs_to用户。

1)不选择

查找

控制台中的此查询工作正常,只需要2个SQL查询。

>> User.find(:all, :limit => 10, :include => [ :user_profile ])

User Load (0.3ms)   SELECT * FROM `users` LIMIT 10
UserProfile Load (0.3ms)   SELECT `user_profiles`.* FROM `user_profiles`
      WHERE (`user_profiles`.user_id IN (1,2,3,...)) 

2)使用user型号

选择查找

我可以使用

User模型中选择列
>> User.find(:all, :select => '`users`.id, `users`.last_name',
     :limit => 10, :include => [ :user_profile ])

User Load (0.3ms)   SELECT `users`.id, `users`.last_name FROM `users` LIMIT 10
UserProfile Load (0.2ms)   SELECT `user_profiles`.* FROM `user_profiles`
      WHERE (`user_profiles`.user_id IN (17510,18087,17508,17288...))

一切正常。请注意,我必须在用户选择的列中设置users.id,因为第二个查询不起作用(返回NULL)。

3)使用user_profile型号

选择查找

但是当我尝试从UserProfile模型中选择列时,我只获得了1个查询,但没有关注我的:select

>> User.find(:all,
     :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
     :limit => 10, :include => [ :user_profile ])

User Load Including Associations (0.6ms) SELECT `users`.`id` AS t0_r0,
  `users`.`login` AS t0_r1, ....
  `user_profiles`.`id` AS t1_r0,
  `user_profiles`.`birth_date` AS t1_r1,
  LEFT OUTER JOIN `user_profiles` ON user_profiles.user_id = users.id LIMIT 10

如您所见,Rails查询包含来自用户的fiels和来自user_profiles的字段,我没有选择。

4)加入方法

Codeit用于join函数的方法:

user_details = User.find(:all,
   :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
   :limit => 10, :joins => [ :user_profile ]
)

User Load (0.2ms) SELECT `users`.id, `users`.last_name, `user_profiles`.permalink
   FROM `users`
   INNER JOIN `user_profiles` ON user_profiles.user_id = users.id
   LIMIT 10

此解决方案适用于SQL查询,但不会在用户和用户配置文件之间建立“链接”。需要10个新查询,而方法1和2只需要2个SQL查询。

 user_details.map(&:user_profile).map(&:permalink)
 UserProfile Load (0.3ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 1) LIMIT 1
 UserProfile Load (0.2ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 2) LIMIT 1
 ... (10 times) ...
 UserProfile Load (0.3ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 10) LIMIT 1

是否有正确的语法可以获得与2个第一个查询相同的结果,但使用:select女巫只选择我的模型中的几列?

1 个答案:

答案 0 :(得分:0)

使用join

User.find(:all,
 :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
 :limit => 10, :joins => [ :user_profile ])

include用于eager loading。当您使用(N+1) users时,它用于解决user_profile查询问题,以便访问user_profile。如果要选择包含的表格columns,则需要使用join。如果使用包含表的列,则会忽略select子句。

修改

user_details = User.find(:all,
   :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
   :limit => 10, :joins => [ :user_profile ]
 )

user_details.map(&:permalink)