从非主键ID数组中获取数据的有效方法?

时间:2014-07-18 15:28:52

标签: ruby postgresql activerecord sinatra

我有一个Ruby / Sinatra应用程序,我正在接收和解析JSON字符串,例如:

[{"id" => "ABCD123", "type" => "image"},
 {"id" => "ABCD234", "type" => "image"},
 {"id" => "ABCD345", "type" => "image"},
 {"id" => "ABCD456", "type" => "image"},
 {"id" => "ABCD567", "type" => "image"}]

在数据库中,我有许多行存储图像的标题。目前,我有一个迭代数组的函数,并执行以下操作:

app.rb

def get_caption(image_id)
  caption = Images.find_by_image_id image_id
end

index.haml

-images.each do |image|
  %div= get_caption(image['id'])

这看起来非常低效,因为该网站对每个图像执行了一次独特的查找,这肯定会在页面的加载时间中加起来。

Images Load (131.6ms)  SELECT  "images".* FROM "images"  WHERE "images"."image_id" = 'ABCD123' LIMIT 1
...
Images Load (131.6ms)  SELECT  "images".* FROM "images"  WHERE "images"."image_id" = 'ABCD567' LIMIT 1

131.6ms * n查询确实很快加起来(我希望这个缓慢的~130ms查询在我们优化生产时也会得到改善,但也许这将是以后的另一个问题!)

有没有更有效的方法来进行此查找?某种方式沿着将caption字段加入数组的方式?

2 个答案:

答案 0 :(得分:2)

您可以采取两项措施来优化这一点:

  1. 一次从数据库中获取所有必需的数据,而不是循环:

    Images.where(image_id: image_ids).index_by(&:image_id)
    
  2. 在数据库的image_id列中创建二级索引:

    add_index :images, :image_id
    
  3. 我想强调的其他一些事情违背了Rails的惯例:

    1. 模型的名称必须是单数,表名必须是复数。这意味着模型的名称应为Image
    2. 我可能错了,但看起来查询是在视图或帮助器中进行的。所有数据库查询都应该在模型中,除了"按主键查找"可以在控制器中。

答案 1 :(得分:0)

写为

def get_captions(image_ids)
  caption = Images.where(image_id: image_ids)
end

image_ids = images.map { |image| image['id'] }
get_captions(image_ids)