mongodb对自定义字段排序后limit为乱序

在使用 mongodb 中,遇到这样一个问题:在对集合进行聚合查询的过程中,通过 $project 添加了一个新字段,然后根据这个新字段进行 $sort 排序,最后再使用 $limit 获取数据,在这个过程中,当 $limit 的值不一样的时候,获取的数据虽然排序了,但是取出的顺序却还是不一样。

例如有如下数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// students 集合

[{
name: 'name-1'
age: 18
},
{
name: 'name-2',
age: 19
},
{
name: 'name-3',
age: 18
},
{
name: 'name-4',
age: 18
},
{
name: 'name-5',
age: 18
},
]

使用 aggrergate 查询:

1
2
3
4
5
6
7
8
9
10
db.students.aggregate([
{
$sort:{
age: 1
}
},
{
$limit: 2
}
])

在上述查询中,不同的 $limit 值,查询出来的结果的顺序不是一致的。

经查,这是由于 $sort 字段的值相同导致的,通过查看官方文档 Version 5.0 文档,其中对于 `$sort 一致性的说明如下:

MongoDB does not store documents in a collection in a particular order. When sorting on a field which contains duplicate values, documents containing those values may be returned in any order.

If consistent sort order is desired, include at least one field in your sort that contains unique values. The easiest way to guarantee this is to include the _id field in your sort query.

MongoDB 在集合中存储文档的顺序是不定的,当对一个有重复值的字段排序时,包含这些值的文档可能会以任意顺序返回。

如果想要保持顺序的一致性,在 sort 语句中应至少保证有一个字段是唯一的。最方便的方式就是在 sort 中包含 _id 字段。

最后,将上述聚合查询改成如下便可恢复正常:

1
2
3
4
5
6
7
8
9
10
11
12
db.students.aggregate([
{
// 先按 age 排序,再按 _id 排序
$sort:{
age: 1,
_id: 1,
}
},
{
$limit: 2
}
])