我在 MongoDB 中有一个集合,如下所示。 -> Mongo Playground 链接
我已按概述和 ID 对集合进行了排序。
$sort{{ overview: 1,_id:1 }}
这会产生这样的集合。
当我过滤集合以仅显示“主题 13”之后的文档时,它按预期工作。
$match{{
_id:{$gt:ObjectId('605db89d208db95eb4878556')}
}}
但是,当我尝试使用“主题 13”之前的文档(即“主题 6”)并使用以下查询时,它无法按我的预期工作。
$match{{
_id:{$lt:ObjectId('605db89d208db95eb4878556')}
}}
结果中我得到的不是“主题 6”,而是以下内容。
我怀疑这种情况正在发生,因为 mongodb 总是在排序之前过滤文档,无论聚合管道中的顺序如何。
请建议我一种在 mongodb 中获取特定“_id”之前的文档的方法。
我的集合中有 600 个文档,这是一个示例数据集。下面是我的完整聚合查询。
[
{
'$sort': {
'overview': 1,
'_id': 1
}
}, {
'$match': {
'_id': {
'$lt': new ObjectId('605db89d208db95eb4878556')
}
}
}
]
MongoDB 通过将排序移动到您的情况的末尾来优化查询性能,因为您已经
$sort
后跟 $match
当您有一个 $sort 后跟 $match 的序列时,$match 会移动到 $sort 之前,以最大限度地减少要排序的对象数量。例如,如果管道由以下阶段组成:
[
{ '$sort': { 'overview': 1, '_id': 1 } },
{ '$match': { '_id': { '$lt': new ObjectId('605db89d208db95eb4878556') } }
]
在优化阶段,优化器将序列转换为以下形式:
[
{ '$match': { '_id': { '$lt': new ObjectId('605db89d208db95eb4878556') } },
{ '$sort': { 'overview': 1, '_id': 1 } }
]
查询计划器结果 -
我们可以看到,在执行排序之后,第一阶段是匹配查询。
{
"stages" : [
{
"$cursor" : {
"query" : {
"_id" : {
"$lt" : ObjectId("605db89d208db95eb4878556")
}
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "video.data3",
"indexFilterSet" : false,
"parsedQuery" : {
"_id" : {
"$lt" : ObjectId("605db89d208db95eb4878556")
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : []
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[ObjectId('000000000000000000000000'), ObjectId('605db89d208db95eb4878556'))"
]
}
}
},
"rejectedPlans" : []
}
}
},
{
"$sort" : {
"sortKey" : {
"overview" : 1,
"_id" : 1
}
}
}
],
"ok" : 1.0
}
在 MongoDB v5.0+ 中,您可以使用
$setWindowFields
通过 $push
和 ["unbounded", -1] 的文档窗口来获取某个文档之前的所有文档
db.collection.aggregate([
{
"$setWindowFields": {
"partitionBy": "$state",
"sortBy": {
"overview": 1,
"_id": 1
},
"output": {
"docsBefore": {
"$push": "$$ROOT",
"window": {
"documents": [
"unbounded",
-1
]
}
}
}
}
},
{
"$match": {
"_id": ObjectId("605db89d208db95eb4878556")
}
}
])