mongodb 使用聚合aggregate 排序后分页结果顺序不一致问题的解决办法及处理过程 解决数据重复

结论

先上结论,在不建立索引的情况下,除使用 _id 之外的字段排序,使用 find 进行分页查询 skiplimit 的查询结果能正常返回顺序,不会受到其他影响。而使用聚合方式 aggregate 查询,其返回结果是不确定的,解决方式是为这个字段建立索引或者增加能确定顺序的排序条件。
在这里插入图片描述

原因

因为在这种查询中,提供的排序条件是不充分的。在进行聚合查询时,数据库已经按照要求按 {count: 1} 完成了排序,但是因为它们的值都一样,不管谁放在前面谁放在后面其实都没有违反要求,因为查询要求只是 count 的升序而已。从数据库的角度来讲,既然没有额外的要求,那当然是以最高效的方式返回结果,也就是不管 count 以外的顺序,因为这样最省资源。
那么什么是最高效?这里涉及一些数据库底层的知识。在单机上,如果没有索引支持,数据库会尝试遍历所有数据,然后做一个内存排序来返回结果,从节省资源的角度,显然这个排序只排到满足了 count 升序为止,其他字段可以说是先到先得。这就造成在count相同时,其他顺序是随机的。它们可能受到:

  1. 自己在磁盘上的顺序影响,因为这会影响到数据库先遍历到哪条记录。并且要注意,每次更新数据时它们在磁盘上的顺序是会变化的;
  2. 在分片集群环境中,结果还受到哪个片先返回数据的影响。分片环境中的排序是先在各个片排好序,再进行一次合并排序;
  3. 理论上还和数据库使用的排序算法相关;

总之,在 aggregate 查询中,如果不指定,数据库不保证返回结果是确定的。
至于解决方案也已经很明确了,指定一个可以完全确定顺序的排序条件,比如:
{$sort: {count: -1, _id: 1}}
但是需要知道的是,这样会让数据库付出额外的操作来保证第二个排序条件的正确性,在实际使用场景中要根据实际情况判断这是不是真的有意义。
另外的方式是给这个字段建立索引,那么查询出来的结果就会按照索引中的顺序返回。

测试过程:

生成20条测试数据

for (let i = 0 ; i < 10 ; i++){
   
    db.getCollection('Test').insert({
   name:String(i), count:NumberInt(0)
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello_czbiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值