MongoDB分頁、排序與遊標

MongoDB分頁、排序與遊標

標籤(空格分隔): MongoDB


一、分頁
1、limit返回指定條數的數據

> db.person.find()
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
>
> db.person.find().limit(3)
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
>

2、skip指定跨度

> db.person.find().skip(3)
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
>

3、limit與skip結合,進行分頁

> db.person.find().skip(0).limit(2)
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
>
> db.person.find().skip(2).limit(2)
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
>
> db.person.find().skip(4).limit(2)
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
>

二、排序
1、sort排序:指定排序的key,大於0爲升序,小於0爲降序。如果指定了多個排序鍵,比如{age:1,name:-1},則是先按age升序排列,對於age鍵相等的文檔,則按name降序排列。

> db.person.find().sort({age:1})
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
>
> db.person.find().sort({age:-1})
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
>

2、排序的先後:從下圖中可以發現,使用sort,始終是先對滿足查詢條件而查詢到的結果集進行排序,然後再進行選取指定的條數或者是跳過指定的條數。它們的關係就是:在數據庫服務器端,先執行sort,然後在排好序的文檔上執行skip,最後按照limit設定的最大數量返回文檔子集即可。

> db.person.find().limit(2).sort({age:1})
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
>
> db.person.find().sort({age:1}).limit(2)
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1003, "name" : "wangwu", "age" : 18 }
>
> db.person.find().skip(2).sort({age:1})
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
>
> db.person.find().sort({age:1}).skip(2)
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
>

3、排序的優先級:由於MongoDB的key可以存儲不同類型的數據,所以排序是有優先級的,如下圖:

> db.person.find()
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1003, "age" : "十八歲", "name" : "wangwu" }
>
> db.person.find().sort({age:1})
{ "_id" : 1004, "name" : "zhaoliu", "age" : 17 }
{ "_id" : 1001, "name" : "lisi", "age" : 20 }
{ "_id" : 1002, "name" : "zhangsan", "age" : 21 }
{ "_id" : 1006, "name" : "zhouba", "age" : 23 }
{ "_id" : 1005, "name" : "sunqi", "age" : 24 }
{ "_id" : 1003, "age" : "十八歲", "name" : "wangwu" }
>

優先級從高到低依次爲:最小值、null、數字、字符串、對象/文檔、數組、二進制、對象ID、布爾、日期、時間戳、正則、最大值。

三、遊標
1、如下圖所示,查詢出某個文檔中某個key(假設類型是數組)的元素個數,使用find函數的返回值是一個遊標,所以需要用到遊標遍歷的方式來遍歷查詢出來的每個文檔,而findOne就可以直接輸出。

> db.person1.find()
{ "_id" : 1002, "name" : "bbb", "books" : [ "JS" ] }
{ "_id" : 1001, "name" : "aaa", "books" : [ "JSP", "JAVA" ] }
>
> var iter = db.person1.find({name:"aaa"})
> while(iter.hasNext()) {
... var obj = iter.next();
... print(obj.books.length);
... }
2
>
> var iter = db.person1.findOne({name:"aaa"})
> iter.books.length
2
>

2、find()函數返回一個遊標。如果在調用find函數時,不保存返回值,其會自動遞歸find返回的遊標,將前20條數據展示在shell中(輸入“it”會繼續顯示下20條),

{ "_id" : 17, "age" : 17 }
{ "_id" : 18, "age" : 18 }
{ "_id" : 19, "age" : 19 }
Type "it" for more
> it
{ "_id" : 20, "age" : 20 }
{ "_id" : 21, "age" : 21 }
{ "_id" : 22, "age" : 22 }

3、遊標到底部就會釋放資源,不能再次讀取,只能讀一遍

4、遊標的銷燬條件:

  • 客戶端發來銷燬信息。
  • 遊標迭代完畢。
  • 默認情況下,遊標超過10分鐘沒用也會被清除。

5、當獲得遊標後,客戶端可以通過對遊標進行一些設置就能對查詢結果進行有效地控制,如可以限制查詢得到的結果數量、跳過部分結果、或對結果集按任意鍵進行排序等,也就是先對遊標進行處理後,再讓訪問數據庫的動作按照指定的意願發生。比如上面分頁和排序中使用的limit()、skip()、sort()等函數,爲什麼這些函數可以進行鏈式調用呢?就是因爲操作遊標的函數返回的都是遊標。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章