有没有更有效的方法来获取此数组?

时间:2015-04-26 20:52:18

标签: sql ruby-on-rails ruby performance sqlite

我有一个模型项,用户可以通过创建新的UpVote或DownVote进行投票。创建UpVote或Downvote时,它会记录用户的IP地址和项目ID。我想列出当前用户没有投票的前100个项目的数组。

到目前为止,这里有我所拥有的:

模式

create_table "up_votes", force: true do |t|
  t.string   "ip"
end

create_table "down_votes", force: true do |t|
  t.string   "ip"
end

模型

class Item < ActiveRecord::Base

  def up_votes_array
    self.up_votes.map(&:ip).to_a
  end

  def down_votes_array
    self.down_votes.map(&:ip).to_a
  end

  def up_voted?(ip)
    self.up_votes_array.include? ip
  end

  def down_voted?(ip)
    self.down_votes_array.include? ip
  end

控制器

@not_voted = Item.where(show: true).select { |item| !item.up_voted?(request.remote_ip) }.select { |thing| !item.down_voted?(request.remote_ip) }.sort_by(&:alphabetical).reverse.first(100).shuffle

它有效,但有一些东西似乎不必要地复杂化,我担心随着我的数据库的增长,它可能会变得低效。有没有更有效的方法来获得这个数组?

我使用的是Rails 4和Sqlite3。

1 个答案:

答案 0 :(得分:2)

我认为对此的理想查询将是这样的:

Item.where(show: true).joins(:up_votes).joins(:down_votes).where('up_votes.ip != ?', request.remote_ip).where('down_votes.ip != ?', request.remote_ip).limit(100)

这将产生一个最佳查询并在你的内存中加载100行,与给出Item的整个表的所有查询相反,所有迭代都是upvotes和downvotes来检查。

您可以将查询联合起来: Item.where(show: true).joins(:up_votes).joins(:down_votes).where('up_votes.ip != ? and down_votes.ip != ', request.remote_ip, request.remote_ip).limit(100)