MongoDB是否能够在不进行多次查询的情况下为大量随机文档提供资金?

e、 g.在加载集合中的所有文档后,我在JS端实现了这一点,这是浪费——因此我只想判断一下,使用一个db查询是否可以做得更好?

我在JS方面所走的道路:

  • 获取所有数据
  • 制作一个ID数组
  • 洗牌ID数组(随机顺序)
  • 将数组拼接到所需的文档数
  • 创建一个文档列表,通过从整个集合中逐个 Select 之前两次操作后留下的ID来创建文档列表

两个主要缺点是我正在加载所有数据,或者我进行了多次查询.

非常感谢您的任何建议

推荐答案

这在很久以前就得到了回答,从那时起,MongoDB已经有了很大的发展.

正如另一个答案所示,MongoDB从3.2版开始现在支持sampling within the Aggregation Framework:

你可以这样做:

db.products.aggregate([{$sample: {size: 5}}]); // You want to get 5 docs

或者:

db.products.aggregate([
  {$match: {category:"Electronic Devices"}}, // filter the results
  {$sample: {size: 5}} // You want to get 5 docs
]);

然而,关于$sample运算符,有some warnings个选项:

(as of Nov, 6h 2017, where latest version is 3.4) => If any of this is not met:

  • $sample是管道的第一阶段
  • N不到集合中总文档的5%
  • 该Collection 包含100多个文档

如果不满足上述任何条件,$sample将执行

就像上一个例子中的$match

OLD ANSWER

你可以一直跑:

db.products.find({category:"Electronic Devices"}).skip(Math.random()*YOUR_COLLECTION_SIZE)

但是顺序不会是随机的,你需要两次查询(一次计数来获得你的集合大小)或者估计它有多大(大约100条记录,大约1000条,大约10000条…)

您还可以向所有文档添加一个带有随机数的字段,并按该数字进行查询.这里的缺点是,每次运行相同的查询时都会得到相同的结果.为了解决这个问题,你可以一直玩限制和跳过,甚至是排序.您还可以在每次获取记录时更新这些随机数(意味着更多查询).

--我不知道您是在使用Mongoose、Mondoid还是直接使用Mongo驱动程序来实现特定的语言,所以我将写下所有关于MongoShell的内容.

因此,你的产品记录应该是这样的:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
}

我建议使用:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
 _random_sample: Math.random()
}

然后你可以做:

db.products.find({category:"Electronic Devices",_random_sample:{$gte:Math.random()}})

然后,可以定期运行,以便定期更新文档的_random_sample字段:

var your_query = {} //it would impact in your performance if there are a lot of records
your_query = {category: "Electronic Devices"} //Update 
//upsert = false, multi = true
db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

或者,只要你检索到一些记录,你就可以更新全部记录,或者只更新少数记录(取决于你检索到的记录数量)

for(var i = 0; i < records.length; i++){
   var query = {_id: records[i]._id};
   //upsert = false, multi = false
   db.products.update(query,{$set:{_random_sample::Math.random()}},false,false);
}

EDIT

要知道

db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

不会很好地工作,因为它会用the same个随机数更新与您的查询匹配的每个产品.最后一种方法效果更好(在检索某些文档时更新它们)

Mongodb相关问答推荐

会话的Mongo-go驱动程序版本.Copy()

在MondoDB中:将对象数组从切片索引数组切片,并通过聚合推入数组

在不知道字段名称的情况下如何引用 MongoDB 中的字段?

避免在 MongoDB 聚合框架中使用 ISODate() 以便管道可以是纯 JSON

MongoDb $filter,然后获取非重复计数

使用 mongo-driver/mongo 使用键/值对中的值表达式查找文档

在 Mongo 聚合中,可以通过分组生成 3 个不同的计数

Pymongo API TypeError: Unhashable dict

我怎样才能排序空值在 mongodb 中是最后排序的?

如何在 Ruby on Rails 环境中使用 Mongoid 进行通配符搜索?

如何在 $lookup Mongodb 的 LocalField 中将字符串转换为 objectId

嵌套在文档数组中的mongodb展开数组

如何使用 mongodb 和 php 正确处理分页查询?

MongoDB聚合排序不起作用

majority和 linearizable的区别

mongo - Ruby连接问题

了解 Mongoose 中的关系和外键

如何向 mongodb 2.6 添加身份验证?

用于 MongoDB 的 Node.js 模块

在mongoose中创建和查找地理位置