最近筆者在工作中遇到一個關(guān)于mongo排序的問題:
文章列表根據(jù)創(chuàng)建時間排序,當(dāng)有多篇文章創(chuàng)建時間相同(批量導(dǎo)入),更新其中的文章順序竟然變了。
筆者趕緊查看了一下代碼,確認更新數(shù)據(jù)時沒有改變數(shù)據(jù)的id和創(chuàng)建時間,第一感覺就是遇到靈異事件了,難道m(xù)ongo的排序還不可靠?無數(shù)個黑人問號???
經(jīng)過多次測試對比發(fā)現(xiàn),只有數(shù)據(jù)第一次更新才會改變順序,后面再操作就不會再變了,嗯第一次更新數(shù)據(jù)會增加updaeTime和updateUser字段,難道這也會影響排序?印象中mongo默認是根據(jù)id來排序的,id沒有變應(yīng)該不會影響排序的呀。
看來問題就是出在這個默認排序上,開始瘋狂的上網(wǎng)查資料,最后找到如下內(nèi)容:
MongoDB的查詢排序默認是未定義的,因此會返回文檔的順序。如果沒有查詢條件,那么將使用自然順序(natural order)。結(jié)果以它們被找到的順序來返回,可能與插入順序(但不能保證)或者索引使用的順序一致。
一些會影響存儲(自然)順序的情況:
. 如果文檔被更新而無法放置在它們當(dāng)前分配的空間,那么會被移動
. 新的文檔可能會插入到因刪除或移動文檔而產(chǎn)生的可用空隙空間如果使用了索引,文檔將以通過索引被找到的順序返回。如果使用了不止一個索引,那么順序內(nèi)部依賴于在重復(fù)數(shù)據(jù)刪除(de-duplication)過程中首先通過哪個索引識別文檔。
如果你需要一個特定順序,那么你必需在你的查詢中包含一個排序。
需要指出的特例是固定集合的自然順序(Capped Collections‘ natural order),因為文檔不能移動且以插入的順序存儲。排序是固定集合特性的部分,確保最舊的文檔先刪除掉。另外,在一個固定集合里文檔不能被刪除或移動。
說明影響自然順序的情況:
如果文檔被移動、刪除,你可能得到不同的結(jié)果集。如果沒有文檔插入、更新、刪除你會獲得相同的結(jié)果。添加索引不會影響文檔在磁盤上的位置。
這下就真相大白了,原來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