MongoDB 學習筆記(三):分頁、排序與遊標

一、分頁

1、limit返回指定條數的數據

2、skip指定跨度

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

二、排序

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

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

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

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

三、遊標

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

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

但是如果通過變量保留find函數的返回值,其不會自動進行遍歷並顯示結果,如果是這樣,調用完find後,此時shell並不會去真正地訪問數據庫,而是等待開始要求獲得結果的時候才向數據庫發送查詢請求。通過調用遊標的hashNext()或next()方法,這樣就會真正訪問數據庫,這是一個懶加載的過程。如下圖:當調用hasNext()時,查詢被髮往數據庫,默認會返回前100條文檔或者前4M的數據(兩者之中較小的),這樣下次next或hasNext都是本地調用了。當這組數據被遍歷完畢,hasNext會再次去訪問數據庫,直到所有結果被返回。

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

3、遊標的銷燬條件:

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

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

四、高級查詢選項

1、查詢分爲普通查詢和包裝查詢,上面演示的各種查詢方式都是普通查詢,可以將普通查詢轉換爲包裝查詢,如下圖:

2、所有查詢在發送到數據庫服務器時,都被提前轉換成了包裝查詢,包裝查詢就是額外使用了一些鍵,如上圖中的"$query"。還有如下一些有用的鍵可用:

  • $maxscan: integer,指定查詢時最多掃描文檔的數量。
  • $min: document,查詢的開始條件。
  • $max: document,查詢的結束條件。
  • $hint: document,指定服務器使用哪些索引進行查詢。
  • $explain: boolean,獲取查詢細節,如用到的索引,結果數量,耗時等,類似於關係數據庫中查看執行計劃,並不會真正執行查詢。
  • $snapshot: boolean,確保查詢的結果是在查詢執行那一刻的一致快照。
  • $orderby: document,排序,等同於sort()的用法。

五、查詢快照

1、從數據庫端調用遊標的hasNext時,數據庫默認會返回100條文檔,然後開始操作文檔。假設對於一個文檔,增大了其大小,並且超過了MongoDB爲文檔設置的預留區域,這時將這條文檔更新到數據庫中,數據庫沒法將其放置在其原始位置上,只能將其移動,通常會移動到集合末尾!這樣使用遊標再次獲取文檔時,有可能又得到這條被修改過的文檔。解決辦法就是對查詢結果進行快照。就是使用上面提到的“$snapshop”高級查詢選項,使用後,查詢就是針對不變的集合視圖運行的。但是實際情況中可以不用這樣做了,因爲MongoDB中,所有返回一組的查詢實際都進行了快照。使用如下圖:

 

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