Mongoid:从两个集合中查询并按日期排序

时间:2012-06-07 22:45:58

标签: ruby-on-rails mongodb pagination mongoid

我目前在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的新手,并想知道最佳解决方案是什么。

有没有办法在MongoDB中跨两个集合进行排序的limit()查询或MapReduce函数?我猜不会有,但在这种情况下肯定会省下很多努力!

我目前认为我有两种选择:

  1. 创建一个主“StreamEntry”类型模型,同时继承信息图和QuickPost,以便两种数据类型都存储在同一个集合中。这个问题是我有现有的数据,我不知道如何将它从旧的集合移动到新的集合。
  2. 使用Streama(https://github.com/christospappas/streama)之类的东西创建单独的Stream / ActivityStream模型。我在这里可以看到的问题是,它需要相当多的前期工作,并且由于隐私设置和编辑/删除项目,流需要经常重建。
  3. 我有没有忽视的选择?我是否过度使用上述选项?这类情况有哪些最佳实践?

    任何信息都会非常感激,到目前为止我真的很喜欢MongoDB,并且希望避免将来陷入这样的陷阱。感谢。

1 个答案:

答案 0 :(得分: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

但是当模型增长或者太不同时,你的第二个解决方案会更好。

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

依赖性破坏会在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