4

(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)

私のアプリの構造は、この設定方法を維持したいのですが、残念ながら、サブクエリではなく外部クエリを制限しているため、非常に低速です。

外部クエリではなく制限とオフセットを受け取るようにサブクエリを公開する方法はありますか?

編集:postgres9.2を使用していることを追加する必要があります。

編集2:この方法で実行したい理由は、ページネーションを実行していて、行の総数の「カウント」を取得する必要があるためです。だから私はこのようなことをします:

@songs = Song.new_songs
...
@pages = @songs.count / 10
...
render @songs.limit(params[:page]).offset(0)

どういうわけかそれを変更した場合、これを完全にやり直す必要があります(これはたくさんの場所にあります)。実際に呼び出されるまで制限しないことで、その間のカウントを実行し、最後のページだけを取得できます。データベースが大きくなるにつれてひどく遅くなることなく、これを内部クエリで実行する方法についてのアドバイスをもっと探していると思います。

4

2 に答える 2

3

私は解決策を試すことができず、私もルビーの専門家ではありませんが、問題を理解している限り、すべてのメソッド呼び出しを渡すが、完全なクエリに制限とオフセットを適用し、その間に制限された 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

于 2012-11-07T18:30:17.510 に答える
0

will_paginate gemの使用を検討する必要があります。これにより、これらすべてを手作業で計算する手間が省けます ;-)

于 2012-11-03T20:51:05.160 に答える