我有一个模型项,用户可以通过创建新的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。
答案 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)