我有一个类似这样的查询(在song.rb中):
def self.new_songs
Song.where(id: Song.grouped_order_published).select_important_stuff
end
稍后在我的应用程序中,然后传递限制和偏移,让我们在控制器中说:
@songs = Song.new_songs.limit(10).offset(10)
我的应用程序的结构方式,我想保留这种设置方法,但不幸的是它确实很慢,因为它限制了外部查询而不是子查询。
有没有办法可以公开子查询,使其接收限制和偏移而不是外部查询?
编辑:我应该添加我使用的是postgres 9.2。
编辑2 :我想以这种方式做的原因是我正在进行分页,我需要获得总行数的“计数”。所以我做了这样的事情:
@songs = Song.new_songs
...
@pages = @songs.count / 10
...
render @songs.limit(params[:page]).offset(0)
如果我以某种方式改变它,我必须完全重做(这在很多地方)。通过不限制它直到它实际被调用,我可以在两者之间进行计数,然后在最后得到页面。我想我正在寻找有关如何使用内部查询完成此建议的建议,而不会随着数据库的增长而变得非常缓慢。
答案 0 :(得分:2)
我无法尝试解决方案,我也不是ruby专家,但据我了解这个问题,你需要一个传递所有方法调用的对象,但限制和偏移到完整查询并存储有限的sub_query与此同时。
它可能看起来像这样:
class LimitedSubquery < Object
# sub_query has to be stored so we can limit/offset it
def initialize(sub_query)
@sub_query = sub_query
end
# Make sure everybody knows we can be used like a query
def self.respond_to?(symbol, include_private=false)
super || full_query.respond_to?(symbol, include_private)
end
# Missing methods are probably meant to be called on the whole query
def self.method_missing(method_sym, *arguments, &block)
if full_query.respond_to?(method_sym)
full_query.send(method_sym, *arguments, &block)
else
super
end
end
# Generate the query for execution
def self.full_query
Song.where(id: @sub_query).select_important_stuff
end
# Apply limit to sub_query
def self.limit(*number)
LimitedSubquery.new(@sub_query.limit(*number))
end
# Apply offset to sub_query
def self.offset(*number)
LimitedSubquery.new(@sub_query.offset(*number))
end
end
而不是称之为
def new_songs
LimitedSubquery.new(Song.grouped_order_published)
end
如果我出错了,请编辑我!
此致
TC
答案 1 :(得分:0)
您应该考虑使用will_paginate gem。这使您远离麻烦,手动计算所有这些; - )