MongoDB 中游標(Cursor)
來自專欄 MongoDB 學習園
引入
db.collection.find()方法返回一個游標結果,訪問文檔需要遍歷這個游標值。 在mongo shell 中返回的游標值沒有賦值給 var 關鍵字定義的變數時會自動遍歷20次並列印這頭20條的文檔結果,如果返回的游標值賦值給了var 關鍵字定義的變數時不會自動遍歷這個游標結果。
Tips:這裡的游標返回默認結果數20可以通過 DBQuery.shellBatchSize 來修改。
手動(遍歷)迭代游標
- 運行游標結果,迭代(遍歷)並列印20條匹配到的文檔:
var myCursor = db.users.find( { type: 2 } );myCursor
- 使用游標的 next()方法訪問文檔:
var myCursor = db.users.find( { type: 2 } );while (myCursor.hasNext()) { print(tojson(myCursor.next()));}
- 列印結果當然也可以使用 printjson() 來替換 print(tojson()):
var myCursor = db.users.find( { type: 2 } );while (myCursor.hasNext()) { printjson(myCursor.next());}
- 也可以使用游標的 forEach() 迭代(遍歷)游標來訪問文檔:
var myCursor = db.users.find( { type: 2 } );myCursor.forEach(printjson);
迭代索引
在mongo shell 中可以使用游標的 toArray() 方法迭代遍歷游標結果,並將結果集放在一個數組中返回。
var myCursor = db.inventory.find( { type: 2 } );var documentArray = myCursor.toArray();var myDocument = documentArray[3];
toArray() 方法會將游標中的所有文檔載入到內存中,同時耗盡這個游標。
有部分Mongodb資料庫驅動提供根據cursor索引位置獲取文檔數據的方法。(例如:cursor[index]). 這是先調用toArray()方法再用索引獲取數組中元素的簡寫。
var myCursor = db.users.find( { type: 2 } );var myDocument = myCursor[1];// 這裡的 myCursor[1] 等價與下面的這行myCursor.toArray() [1];
游標行為
- 關閉不活動的Cursor
默認情況下,伺服器會自動關閉超過10分鐘活躍的或客戶端已耗盡的游標。想不使用這個默認行為在 mongo shell 中可以使用ursor.noCursorTimeout()方法:
var myCursor = db.users.find().noCursorTimeout();
設定noCursorTimeout這個選項後,你必須通過cursor.close()方法手動關閉, 或者耗盡這個游標。
- 游標隔離
當游標返迴文檔時,其他操作可能與查詢交織。對於MMAPv1存儲引擎,如果文檔發生更改,對文檔的寫入操作可能導致游標多次返迴文檔。若要處理此情況,請參閱游標快照信息。
- 游標批處理
MongoDB伺服器將結果打包返回. 數據包的大小不能超過默認BOSN文檔大小(16M)maximum BSON document size。 可以通過batchSize()和limit()來修改返回結果集。
3.4 新版本 find(), aggregate(), listIndexes, 和listCollections每批返回最大16M的數據。batchSize()可以設置一個更小的限制, 而不是最大的限制。
find()和aggregate() 默認初始集合文檔數量是101。後來的getMore操作,沒有默認集合文檔數量限制, 只是有16M最大位元組數限制。
Tips:有sort排序沒有索引的查詢操作時, 返回結果前, 伺服器必須將全部數據載入進內存中來實現排序。
遍歷結果集到達返回數據的末尾時, 如果有更多的數據, cursor.next()方法會執行getMore operation操作來得到下一批數據。可以通過objsLeftInBatch()方法來查看在當前數據還有多少數據沒有遍歷.
var myCursor = db.inventory.find();var myFirstDocument = myCursor.hasNext() ? myCursor.next() : null;myCursor.objsLeftInBatch();
游標信息
db.serverStatus()方法返回一個包括了metrics欄位的文檔。metrics欄位的metrics.cursor有以下信息:
- 自伺服器器啟動以來超時游標數;
- 使用DBQuery.Option.noTimeout 選項防止超時打開的游標數;
- pinned 打開的游標數量;
- 打開游標的總數量;
db.serverStatus().metrics.cursor
結果顯示
{ "timedOut" : <number> "open" : { "noTimeout" : <number>, "pinned" : <number>, "total" : <number> }}
譯自官網: https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/
游標方法: https://docs.mongodb.com/manual/reference/method/#js-query-cursor-methods
微信公眾號:MongoDB學習園
MongoDB 中游標(Cursor)推薦閱讀:
※常見的SQL筆試題和面試題
※寫《論文》的大資料庫!(1-92)
※《A Critique of ANSI SQL Isolation Levels》論文實驗
※誤刪了公司資料庫,但我還是活下來了
※SQL每日一練【180608】