gpt4 book ai didi

MongoDB:分页导致重复的奇怪排序行为

转载 作者:行者123 更新时间:2023-12-04 14:19:23 25 4
gpt4 key购买 nike

这里我刚刚创建了一个包含 9 个文档 {id, name} 的集合。所有文档的字段 name 都具有相同的值“A”。

[
{
"name": "A",
"id": 1
},
{
"name": "A",
"id": 2
},
{
"name": "A",
"id": 3
},
{
"name": "A",
"id": 4
},
{
"name": "A",
"id": 5
},
{
"name": "A",
"id": 6
},
{
"name": "A",
"id": 7
},
{
"name": "A",
"id": 8
},
{
"name": "A",
"id": 9
}
]

我想在按名称排序后对这个集合进行分页(在我的情况下按名称排序是没有用的,但我这样做是为了证明奇怪的行为),3 x 3。(页面大小为 3)。

当我使用 $skip 0、$limit 3 执行聚合管道时(第一页):

db.collection.aggregate([
{
"$sort": {
"name": 1
}
},
{
"$skip": 0
},
{
"$limit": 3
}
])

结果是:

[
{
"_id": ObjectId("5a934e000102030405000000"),
"id": 1,
"name": "A"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"id": 2,
"name": "A"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"id": 3,
"name": "A"
}
]

而现在当我想得到下面的页面($skip 3, $limit 3)时,结果是:

[
{
"_id": ObjectId("5a934e000102030405000000"),
"id": 1,
"name": "A"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"id": 3,
"name": "A"
},
{
"_id": ObjectId("5a934e000102030405000005"),
"id": 6,
"name": "A"
}
]

我们注意到再次提取了 id 为 1 和 3 的文档。这最终导致分页错误(重复)!

当在非唯一列上排序会导致这种奇怪的行为时,您如何解释这一点?

重现问题 https://mongoplayground.net/p/hP7CMtA3b2f

最佳答案

运行时:sort -> skip(3) -> limit(3)

Mongo 查询优化器将查询顺序更改为:sort + limit(6) -> skip(3)

因此 mongo 正在使用“limit+skip”的值进行“限制”。而排序和限制不是两个不同的阶段,而是一个阶段。这种查询优化的原因是找到最大的 6 个元素并对它们进行排序比首先对所有元素进行排序并获得前 6 个更好

因此出现了这种奇怪的行为。证明解释结果:

{
"stages" : [
{
"$cursor" : {
"query" : {},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "5ceb96f75538551e7d3bcdb8_lav.test",
"indexFilterSet" : false,
"parsedQuery" : {},
"winningPlan" : {
"stage" : "COLLSCAN",
"direction" : "forward"
},
"rejectedPlans" : []
}
}
},
{
"$sort" : {
"sortKey" : {
"name" : 1
},
"limit" : NumberLong(6)
}
},
{
"$skip" : NumberLong(3)
}
],
"ok" : 1.0,
"operationTime" : Timestamp(1560596833, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1560596835, 4),
"signature" : {
"hash" : { "$binary" : "ouhjbA5FjqF/EE4ySVpHdvG8HaM=", "$type" : "00" },
"keyId" : NumberLong(6691284195030859777)
}
}
}

在名称字段上添加索引,排序将变为稳定排序。你会得到想要的结果。

关于MongoDB:分页导致重复的奇怪排序行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56609607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com