最近笔者在工作中遇到一个关于mongo排序的问题:
文章列表根据创建时间排序,当有多篇文章创建时间相同(批量导入),更新其中的文章顺序竟然变了。
笔者赶紧查看了一下代码,确认更新数据时没有改变数据的id和创建时间,第一感觉就是遇到灵异事件了,难道mongo的排序还不可靠?无数个黑人问号???
经过多次测试对比发现,只有数据第一次更新才会改变顺序,后面再操作就不会再变了,嗯第一次更新数据会增加updaeTime
和updateUser
字段,难道这也会影响排序?印象中mongo默认是根据id
来排序的,id
没有变应该不会影响排序的呀。
看来问题就是出在这个默认排序上,开始疯狂的上网查资料,最后找到如下内容:
MongoDB的查询排序默认是未定义的,因此会返回文档的顺序。如果没有查询条件,那么将使用自然顺序(natural order)。结果以它们被找到的顺序来返回,可能与插入顺序(但不能保证)或者索引使用的顺序一致。
一些会影响存储(自然)顺序的情况:
. 如果文档被更新而无法放置在它们当前分配的空间,那么会被移动
. 新的文档可能会插入到因删除或移动文档而产生的可用空隙空间如果使用了索引,文档将以通过索引被找到的顺序返回。如果使用了不止一个索引,那么顺序内部依赖于在重复数据删除(de-duplication)过程中首先通过哪个索引识别文档。
如果你需要一个特定顺序,那么你必需在你的查询中包含一个排序。
需要指出的特例是固定集合的自然顺序(Capped Collections‘ natural order),因为文档不能移动且以插入的顺序存储。排序是固定集合特性的部分,确保最旧的文档先删除掉。另外,在一个固定集合里文档不能被删除或移动。
说明影响自然顺序的情况:
如果文档被移动、删除,你可能得到不同的结果集。如果没有文档插入、更新、删除你会获得相同的结果。添加索引不会影响文档在磁盘上的位置。
这下就真相大白了,原来mongo默认排序是自然排序而不是我认为的id
排序,赶紧再加上个按id
排序问题解决。
参考资料:
http://www.mamicode.com/info-detail-1430295.html
https://docs.mongodb.com/manual/reference/method/cursor.sort/#return-natural-order
https://docs.mongodb.com/manual/indexes/#default-id-index