Mongoid随机文件

GTD*_*Dev 9 ruby ruby-on-rails mongodb mongoid

假设我有一个用户集合.有没有办法使用mongoid在集合中找到n个随机用户,它不会返回同一个用户两次?现在让我们假设用户集合如下所示:

class User
  include Mongoid::Document
  field :name
end
Run Code Online (Sandbox Code Playgroud)

简单吧?

谢谢

tot*_*rio 17

如果您只想要一个文档,并且不想定义新的条件方法,则可以执行以下操作:

random_model = Model.skip(rand(Model.count)).first
Run Code Online (Sandbox Code Playgroud)

如果要根据某些条件找到随机模型:

criteria = Model.scoped_whatever.where(conditions) # query example
random_model = criteria.skip(rand(criteria.count)).first
Run Code Online (Sandbox Code Playgroud)


Dan*_*aly 13

最佳解决方案将取决于预期的集合大小.

对于微小的集合,只需获取所有这些和.shuffle.slice!

对于小尺寸的n,你可以逃避这样的事情:

result = (0..User.count-1).sort_by{rand}.slice(0, n).collect! do |i| User.skip(i).first end
Run Code Online (Sandbox Code Playgroud)

对于大尺寸的n,我建议创建一个"随机"列进行排序.详情请见:http ://cookbook.mongodb.org/patterns/random-attribute/ https://github.com/mongodb/cookbook/blob/master/content/patterns/random-attribute.txt


Cyr*_*ris 6

MongoDB 3.2拯救了$sample(链接到doc)

编辑:最近的Mongoid实现了$ sample,所以你可以打电话YourCollection.all.sample(5)

以前版本的mongoid

Mongoid在sampleMongoid 6之前不支持,因此您必须使用Mongo驱动程序运行此聚合查询:

samples = User.collection.aggregate([ { '$sample': { size: 3 } } ])
# call samples.to_a if you want to get the objects in memory
Run Code Online (Sandbox Code Playgroud)

你可以用它做什么

我相信功能性应该很快成为Mongoid,但与此同时

module Utility
  module_function
  def sample(model, count)
    ids = model.collection.aggregate([ 
      { '$sample': { size: count } }, # Sample from the collection
      { '$project': { _id: 1} }       # Keep only ID fields
    ]).to_a.map(&:values).flatten     # Some Ruby magic

    model.find(ids)
  end
end

Utility.sample(User, 50)
Run Code Online (Sandbox Code Playgroud)