0

現在、Rails アプリに次のコントローラー メソッドがあります。

def index
  @entries = []
  @entries << QuickPost.where(:user_id.in => current_user.followees.map(&:ff_id) << current_user.id)
  @entries << Infographic.where(:user_id.in => current_user.followees.map(&:ff_id) << current_user.id)
  @entries.flatten!.sort!{ |a,b| b.created_at <=> a.created_at }

  @entries = Kaminari.paginate_array(@entries).page(params[:page]).per(10)
end

これは非常に非効率的であることを認識しているため、同じ目標を達成するためのより良い方法を探していますが、MongoDB は初めてで、最善の解決策は何かと考えています。

2 つのコレクションにわたって MongoDB でソートされた limit() クエリまたは MapReduce 関数を作成する方法はありますか? ないと思いますが、この場合、確かに多くの労力を節約できます!

現在、次の 2 つのオプションがあると考えています。

  1. マスター「StreamEntry」型モデルを作成し、インフォグラフィックと QuickPost の両方を継承させて、両方のデータ型が同じコレクションに格納されるようにします。これに関する問題は、既存のデータがあり、それを古いコレクションから新しいコレクションに移動する方法がわからないことです。
  2. Streama (https://github.com/christospappas/streama) などを使用して別の Stream/ActivityStream モデルを作成します。ここで見られる問題は、かなりの事前作業が必要であり、プライバシー設定とアイテムの編集/削除のために、ストリームを頻繁に再構築する必要があることです.

私が見落としたオプションはありますか?上記のオプションを使用して設計しすぎていませんか? この種の状況には、どのようなベスト プラクティスがありますか?

どんな情報でも大歓迎です。私は今のところ MongoDB が本当に好きで、将来このような落とし穴に陥るのを避けたいと思っています。ありがとう。

4

1 に答える 1

2

継承ソリューションは問題ありませんが、継承されたモデルが近い場合。例えば ​​:

class Post < BasePost
  field :body, type: String
end
class QuickPost < BasePost
end
class BasePost
  field :title, type: String
  field :created_at, type: Time
end

しかし、モデルが大きくなったり、モデルが大きく異なったりすると、2 番目のソリューションの方が優れています。

class Activity
  include Mongoid::Document

  paginates_per 20

  field :occurred_at, :type => Time, :default => nil
  validates_presence_of :occurred_at

  belongs_to :user
  belongs_to :quick_post
  belongs_to :infographic

  default_scope desc(:occurred_at)
end

たとえば、次のようになります。

class QuickPost
  include Mongoid::Document
  has_one :activity, :dependent => :destroy
end

依存する destroy は、QuickPost が破棄されるときにアクティビティを破棄します。has_many と adapt を使用できます。

アクティビティを作成するために、オブザーバーを作成できます。

class ActivityObserver < Mongoid::Observer
  observe :quick_post, :infographic

  def after_save(record)
    if record.is_a? QuickPost
      if record.new_record?
        activity = record.build_activity
        activity.user = record.user
        # stuff when it is new
      else
        activity = record.activity
      end
      activity.occurred_at = record.occurred_at
      # common stuff
      activity.save
    end
  end
end
于 2012-06-08T08:32:42.157 に答える