有一個List ArrayList<Long> al=new ArrayList<Long>();裏麵存儲了從外部獲取的數據的ID並且進行了排序(隨機抽取的ID,按照先後放入LIST),然後把這些ID在mongoDB通過inObj.put("_id", new BasicDBObject("$in", list));進行in查詢,獲取後的結果並不和LIST中ID的順序一樣,搜索了一下,有文章說不指定排序的話,mongodb會按照$natural進行排序,但是我測試了一下,並不是這樣。
現在問題是怎麼才能讓mongodb按照list的排序獲取結果呢
伊谢尔伦2017-04-21 10:58:29
這是個很好的問題。其實你查的文章沒有說錯,不指定排序,就是依照自然排序來排的。只不過這個自然排序是指按照_id
的自然排序去排。你的list
只是一个查询条件,就相当于x > max AND x < min
指定的一个查询范围,跟排序完全没有关系,不论是什么数据库系统,都会在你指定的这个list
範圍內找到資料後再按自身的排序方法來排序。
我的建議是你還是照這種方法去取值,取出後,自己在java程式裡循環一遍,然後跑出排序後的陣列。
伊谢尔伦2017-04-21 10:58:29
@joyqi 的說法不太對,MongoDB裡的自然排序(也就是按$natural字段排序)與按_id字段排序是不同的。自然排序是按資料在資料檔案中的組織順序來排序的。
你可以explain一下你的查詢,就能看到它利用索引的情況,例如你用下面的語句插入資料:
> db.test.insert({a:2,b:1}) > db.test.insert({a:1,b:2}) > db.test.insert({a:2,b:3}) > db.test.insert({a:1,b:4})
在你不對a欄位加索引時,會得到下面的結果,以下是自然排序的結果:
> db.test.find({a:{$in:[1,2]}}) { "_id" : ObjectId("4f509380ea72116cb2137567"), "a" : 2, "b" : 1 } { "_id" : ObjectId("4f509380ea72116cb2137568"), "a" : 1, "b" : 2 } { "_id" : ObjectId("4f509380ea72116cb2137569"), "a" : 2, "b" : 3 } { "_id" : ObjectId("4f509380ea72116cb213756a"), "a" : 1, "b" : 4 }
因為這時候MongoDB是排表的查詢,掃到一條資料滿足條件就加入回傳清單。所以是按自然順序來做的。
而如果你加上索引再查,會得到下面的結果
> db.test.ensureIndex({a:1}) > db.test.find({a:{$in:[1,2]}}) { "_id" : ObjectId("4f509537ea72116cb213756f"), "a" : 1, "b" : 4 } { "_id" : ObjectId("4f509530ea72116cb213756d"), "a" : 1, "b" : 2 } { "_id" : ObjectId("4f509534ea72116cb213756e"), "a" : 2, "b" : 3 } { "_id" : ObjectId("4f50952cea72116cb213756c"), "a" : 2, "b" : 1 }
可以看到,結果按a為1,a為2分開了,因為按索引查詢時,相當於是在索引中查多段數據,這裡的例子裡,相當於是查了a的範圍為[1,1]和[2,2]兩個範圍的數據,這兩次在邏輯上是串列的,先查[1,1]的數據,再查[2,2]的數據,所以這裡a為1和2的分開了。
伊谢尔伦2017-04-21 10:58:29
沒用過mongodb,不過感覺這個問題的答案和別的關係型資料庫一樣的。如果你在關係型資料庫中這樣插入ID,而ID又是主鍵的話,那麼資料庫會自動按照ID的值進行排序,因為主鍵本身就是一個聚集索引,要達到你想要的效果很簡單,不要自己生成ID,讓Mongodb產生一個自動自增的ID,這樣插入時排序是按照這個自增值排序的,你讀取的時候也是按照插入順序讀取的。