避免在ActiveRecord中进行重复查询-Ruby on Rails

时间:2019-04-02 11:45:43

标签: ruby-on-rails activerecord

我有一些简单查询的代码,我试图通过将它们压缩到一个查询中来对其进行优化。但是我不知道如何。

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first
posts_with_updated_name = posts.map { |post| post[:name] = "UPDATE_" + post[:name] }

我希望有一个查询,该查询将在第一行执行,然后 posts 是一个数组,可以在该数组上执行第2、3和4行的操作。我得到的是,我有3个独立的查询。知道如何将其优化为单个查询吗?

LE:您可以假设num_postsfirst_postposts_with_updated_name只是我以后需要使用的变量

2 个答案:

答案 0 :(得分:2)

由于将ActiveRecord::Relation对象转换为Array可能会为大型数据库消耗大量内存(甚至可能耗尽内存),因此我将执行以下操作,但仍会使用(2 +批数)SQL查询,但您的应用程序可以长期扩展。

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# || is a PostgreSQL operator for string concatenation
# if you are using MySQL check out CONCAT instead
posts_with_updated_name = posts.select('posts.*', "'UPDATE_' || name AS updated_name")

# example usage
posts_with_updated_name.find_each do |post|
  puts post.id
  puts post.name
  puts post.updated_name
end

# example output:
# 6
# 'Spider Man is Back'
# 'UPDATE_Spider Man is Back'
# 84
# 'Hello World'
# 'UPDATE_Hello World'

推荐的解决方案

1。临时“更新名称”

我不会将“更新后的名称”存储到变量中,而是仅按需添加/添加字符串,如下所示:

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# somewhere in your code where you are actually already gonna be looping over `posts`
posts.find_each do |post|
  updated_name = "UPDATE_#{post.name}'"
  # do something here about updated name
end

2。永久的“更新名称”

或者...如果此“更新名称”值是整个应用程序的永久逻辑,则只需在模型中编写一个方法:

app / models / post.rb

class Post < ApplicationRecord
  # ...

  def updated_name
    "UPDATE_#{name}"
  end
end

然后在代码中,您只需执行以下操作,而无需设置“更新名称”的值,

posts = Post.where(category: "article")
num_posts = posts.count
first_post = posts.first

# example:
puts first_post.updated_name
# => 'UPDATE_Hello World'

答案 1 :(得分:1)

我不确定我是否很好地理解了您的问题,但是我认为您想将ActiveRecord集合转换为数组?如果是这样,您可以使用posts = Post.where(category: "article").to_a