MongoDB是否能够在不进行多次查询的情况下为大量随机文档提供资金?
e、 g.在加载集合中的所有文档后,我在JS端实现了这一点,这是浪费——因此我只想判断一下,使用一个db查询是否可以做得更好?
我在JS方面所走的道路:
- 获取所有数据
- 制作一个ID数组
- 洗牌ID数组(随机顺序)
- 将数组拼接到所需的文档数
- 创建一个文档列表,通过从整个集合中逐个 Select 之前两次操作后留下的ID来创建文档列表
两个主要缺点是我正在加载所有数据,或者我进行了多次查询.
非常感谢您的任何建议
MongoDB是否能够在不进行多次查询的情况下为大量随机文档提供资金?
e、 g.在加载集合中的所有文档后,我在JS端实现了这一点,这是浪费——因此我只想判断一下,使用一个db查询是否可以做得更好?
我在JS方面所走的道路:
两个主要缺点是我正在加载所有数据,或者我进行了多次查询.
非常感谢您的任何建议
这在很久以前就得到了回答,从那时起,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将执行
就像上一个例子中的$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个随机数更新与您的查询匹配的每个产品.最后一种方法效果更好(在检索某些文档时更新它们)