【发布时间】:2019-07-02 08:57:12
【问题描述】:
我的目标是以最简洁、最有效的方式编写下面的查询,并尽量减少对数据库的影响。提前感谢任何指导。
我检索到了一些属于user 的记录,如下所示:
english_shows = @user.shows.where(language: 'english')
假设shows 属于不同的categories(使用外键),如下所示:
<ActiveRecord::Relation [
<Show id: 1, category_id: 1, title: 'Rick and Morty'>,
<Show id: 2, category_id: 2, title: 'Black Mirror'>,
<Show id: 3, category_id: 3, title: 'Stranger Things'>,
<Show id: 4, category_id: 3, title: 'Game of Thrones'>,
...
]
如果我想获取每个类别的shows 的标题,我知道我可以像这样使用select。 ([编辑]实际上,两者都会访问数据库两次)。 p>
where 可以做同样的事情,但这会导致额外的数据库调用。
# Using select
cartoons = english_shows.select { |show| show.category_id == Category.find_by(name: 'cartoon').id}.pluck(:title)
# Using where
cartoons = english_shows.where(category_id: Category.find_by(name: 'cartoon').id)pluck(:title)
但是,select 方法仍然会导致多行长代码(在我的实际用例中,我有更多的类别类型)。循环遍历这样的记录是否更干净(取自此 SO answer)?
cartoons, science_fiction, fantasy = [], [], []
@cartoon_id = Category.find_by(name: 'cartoon')
@science_fiction_id = Category.find_by(name: 'cartoon')
@fantasy_id = Category.find_by(name: 'cartoon')
english_shows.each do |show|
cartoons << show if show.category_id == @cartoon_id
science_fiction << show if show.category_id == @science_fiction_id
fantasy << show if show.category_id == @fantasy_id
end
【问题讨论】:
-
"这只会访问数据库一次" –
select从哪里获取记录?english_shows已经是数组还是关系了? -
我猜这种理解是错误的——当我之前尝试过时,似乎
select只是使用了变量中的内容,但刚刚尝试它我意识到它仍然会命中数据库以获取值english_shows再次。在这种情况下,我的问题仍然存在 - 是循环遍历,使用select,还是使用where? -
where 通常会导致执行速度更快 - select 将遍历集合中的每条记录并对其应用条件 - where 将在一个事务中执行所有这些操作
标签: ruby-on-rails database loops select