在运行过滤查询之前,是否可以对Mongo集合运行排序?我有一个较旧的代码,其中我使用的方法是从数据库中获取随机结果,方法是在0和1之间随机浮动,然后使用findOne
查询以获得值更大的第一个文档而不是当时生成的随机浮动。样本集很小,所以当时没有注意到问题,但最近注意到,通过一个查询,我几乎总是得到相同的值。 "第一"文件随机> .9,所以几乎每个查询都首先匹配它。
我意识到,要使这个解决方案起作用,我需要随机排序,然后找到大于我随机的第一个值。据我了解,这不像过去那样是必要的解决方案,因为$sample
存在于3.2,但我想知道如何做到这一点会很好吗?另外,我的理解是$sample
可以多次返回同一文档(显然N> 1,因此不能直接适用于我的问题)。
例如,以下数据:
> db.links.find()
{ "_id" : ObjectId("553c072bc87652a80e00002a"), "random" : 0.9162904409691691 }
{ "_id" : ObjectId("553c3332c87652c80700002a"), "random" : 0.00427396921440959 }
{ "_id" : ObjectId("553c3c5cc87652a80e00002b"), "random" : 0.2409569111187011 }
{ "_id" : ObjectId("553c3c66c876521c10000029"), "random" : 0.35101076657883823 }
{ "_id" : ObjectId("553c3c6ec87652200700002e"), "random" : 0.3234482416883111 }
{ "_id" : ObjectId("553c68d5c87652a80e00002c"), "random" : 0.5221220930106938 }
任何尝试运行db.mycollection.findOne({'random': {'$gte': x}})
,其中x是高达.91的任何值,总是返回第一个对象(_id 553c072)。任何更大的回报都没有。如果我可以按random
值按升序排序然后过滤,它会继续搜索,直到找到正确的值。
答案 0 :(得分:1)
我强烈建议您放弃自定义解决方案,只需切换到使用MongoDB内置$sample阶段,该阶段将从您的集合中返回随机结果。
根据您的评论编辑:
以下是您可以执行最初要求的方式:
db.links.find({ "random": { $gte: /* put your value here */ } })
.sort({ "random": 1 /* sort by "random" field in ascending order */ })
.limit(1)
您可以,但也不需要使用aggregation framework:
db.links.aggregate({
$match: {
"random": {
$gte: /* put your value here */ // filter the collection
}
}
}, {
$sort: {
"random": 1 // sort by "random" field in ascending order
}
}, {
$limit: 1 // return only the first element
})