我有以下代码:
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>
<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>
在我的日志中,我看到了:
Photo Load (0.4ms) SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 1
Photo Load (0.7ms) SELECT "photos".* FROM "photos" WHERE ("photos"."photo_album_id" = 72) ORDER BY photos.created_at DESC, photos.version DESC LIMIT 4
调试之后,即使4个记录的第一个匹配找到了link_to所需的第一个查询,它就是生成额外数据库命中的link_to。
有没有办法防止此查询多次命中数据库2次。我只想获得限制4的查询,这应该为应用程序提供所需的所有信息。
思想?
更新
我也希望能够输出以下内容:
<%= @photos.first.photo_album.title %>
但是这也会再次击中数据库。对于上述所有方法,只能为数据库命中一次? thxs
答案 0 :(得分:1)
我相信第一次点击会在您展示的内容之前发生在代码中。
您确定
行吗?<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>
点击数据库?由于延迟加载,我认为只有在运行第二行时,数据库才会被命中。
我认为你需要做更多调试才能看到第一个数据库命中的位置。
至于您的更新,请将第一行更改为
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).includes(:photo_albums) %>
在同一查询中加载相册。
答案 1 :(得分:1)
在你的情况下,
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4) %>
返回一个ActiveRecord::Relation
对象,在你调用enumerable
方法之前它不会命中。或者,您可以在其上调用first
,all
或last
。这是在你的第二行完成的,
<%= link_to 'Image Set', project_photo_album_path(storyitem.project, @photos.first.photo_album_id) %>
代码中的其他位置是否使用@photos
?
如果您想完全避免第二次通话,只需拨打all
上的@photos
方法即可。像这样:
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).all %>
然后对于所有后续使用,它将不会再次击中DB。如果您还想避免photo_album
的数据库匹配,那么您可以使用include
:
<% @photos = Photo.where(:photo_album_id => storyitem.feeded_id).limit(4).include(:photo_albums).all %>