MongoDB 中游標(Cursor)

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> }}

譯自官網: docs.mongodb.com/manual

游標方法: docs.mongodb.com/manual

微信公眾號:MongoDB學習園

MongoDB 中游標(Cursor)?

www.xuexiyuan.cn


推薦閱讀:

常見的SQL筆試題和面試題
寫《論文》的大資料庫!(1-92)
《A Critique of ANSI SQL Isolation Levels》論文實驗
誤刪了公司資料庫,但我還是活下來了
SQL每日一練【180608】

TAG:MongoDB | SQL | 資料庫 |