學習MongoDB 六: MongoDB查詢(遊標操作、遊標資訊)(三),mongodb遊標
一、簡介
db.collection.find()可以實現根據條件查詢和指定使用投影運算子返回的欄位省略此參數返回匹配文檔中的所有欄位。並返回到匹配文檔的遊標,可以隨意修改查詢限制、跳躍、和排序次序的功能。
二、db.collection.findOne ()
db.collection. findOne ()返回滿足指定查詢條件的文檔。如果多個文檔滿足查詢,該方法返回第一個文檔,根據自然順序返迴文件在磁碟上的順序,在覆蓋的集合中,自然順序與插入順序相同。
文法:
db.collection.findOne(query, projection)
參數 |
類型 |
描述 |
query |
document |
可選. 使用查詢操作符指定查詢條件 |
projection |
document |
指定使用投影運算子返回的欄位省略此參數返回匹配文檔中的所有欄位 |
Projection文法:
{ field1: <boolean>, field2: <boolean> ... }
說明:
1或者true表示返回欄位
0或者false表示不返回該欄位
先插入資料
>db. orders.insert([{ "onumber" : "001", "date" : "2015-07-02", "cname" : "zcy1", "items" :[ { "ino" : "001", "quantity" :2, "price" : 4.0 },{ "ino" : "002", "quantity" : 4, "price" : 6.0 } ]},{ "onumber" : "002", "date" : "2015-07-02", "cname" : "zcy2", "items" :[ { "ino" : "001", "quantity" :2, "price" : 4.0 },{ "ino" : "002", "quantity" :6, "price" : 6.0 } ]}])
我們用db.orders.find()查詢時返回多條記錄
>db.orders.find({"date":"2015-07-02"})
我們執行db.orders.findOne()時,只返回第一條記錄
例子:
<span style="font-size:18px;"> >db.orders.findOne({"date":"2015-07-02"})</span>
二、遊標的遍曆
db.collection.find()可以實現根據條件查詢和指定使用投影運算子返回的欄位省略此參數返回匹配文檔中的所有欄位。並返回到匹配文檔的遊標,可以隨意修改查詢限制、跳躍、和排序次序的功能。
1、我們先通過javascript指令碼向集合中填充10000條文檔,然後執行db.collection.find()執行查詢文檔
> for(var i=0;i<10000;i++){...db.items.insert({"ino":i,"quantity":i});... }WriteResult({ "nInserted" : 1 })> db.items.find(){ "_id" :ObjectId("55a66f3c7db4e9f2ef681076"), "ino" : 0,"quantity" : 0 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681077"), "ino" : 1,"quantity" : 1 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681078"), "ino" : 2,"quantity" : 2 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681079"), "ino" : 3,"quantity" : 3 }{ "_id" : ObjectId("55a66f3c7db4e9f2ef68107a"),"ino" : 4, "quantity" : 4 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107b"), "ino" : 5,"quantity" : 5 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107c"), "ino" : 6,"quantity" : 6 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107d"), "ino" : 7, "quantity": 7 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107e"), "ino" : 8,"quantity" : 8 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef68107f"), "ino" : 9,"quantity" : 9 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681080"), "ino" : 10,"quantity" : 10 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681081"), "ino" : 11,"quantity" : 11 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681082"), "ino" : 12,"quantity" : 12 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681083"), "ino" : 13,"quantity" : 13 }{ "_id" : ObjectId("55a66f3c7db4e9f2ef681084"),"ino" : 14, "quantity" : 14 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681085"), "ino" : 15,"quantity" : 15 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681086"), "ino" : 16,"quantity" : 16 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681087"), "ino" : 17,"quantity" : 17 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681088"), "ino" : 18,"quantity" : 18 }{ "_id" :ObjectId("55a66f3c7db4e9f2ef681089"), "ino" : 19,"quantity" : 19 }Type "it" for more>
我們db.collection.find()執行查詢文檔時,發現Mongo shell如果沒有分配給一個使用var關鍵字的變數迭代資料時,游標自動迭代前20個文檔的結果返回。
輸入“it”後會顯示後二十條的資料。
2、你可以使用DBQuery.shellbatchsize改變迭代次數(每頁就顯示10條記錄)
例子:
>DBQuery.shellBatchSize = 10
現在游標自動迭代前10個文檔的結果返回
3、我們定義一個變數來儲存這個遊標
例子:
> var cursor=db.items.find()
用一個變數來儲存遊標,不會自動輸出資料的,需要我們自己實現這個查詢結果的遊標進行遍曆。
4、對遊標進行遍曆
>var cursor=db.items.find() >while(cursor.hasNext()){ var doc = cursor.next(); printjson(doc); };
或者
forEach()迴圈遍曆:
>cursor.forEach( function(doc) { printjson(doc);});
當你遍曆遊標到返回的批處理結束,如果有更多的結果,cursor.next()將執行更多的操作來擷取下一批。
MongoDB伺服器返回的查詢結果, 當調用cursor.hasNext()時,MongoDB批量的大小不會超過最大BSON文檔大小,然而對於大多數查詢,第一批返回101文檔或足夠的檔案超過1 MB,後續的批大小為4 MB。如果第一批是返回101個文檔時,遍曆完時,執行hasNext,會到資料庫查詢結果,直到所有結果都被返回,遊標才會結關閉。
我們可以通過可以使用objsleftinbatch()方法來查看,每次返迴文檔數量或者大小,如下面的例子:
>var cursor=db.items.find() >cursor .objsLeftInBatch();
當我們剛執行查詢時,執行cursor .objsLeftInBatch();方法會顯示101 ,這說明第一批返回101文檔(101文檔沒超過1MB)
我們遍曆完101個文檔時,當我們執行cursor.hasNext()時,第二批會在返回101文檔嗎?
我們先遍曆完101個文檔,如下面的例子:
>for(vari=0;i<101;i++){ var doc = cursor.next(); printjson(doc); }
這時我們迭代完第一批返回的結果,我們在執行cursor.hasNext();時,會到資料庫查詢下一批結果,我們objsLeftInBatch方法查看返迴文檔大小,如下面的例子:
>cursor.hasNext(); >cursor .objsLeftInBatch();
這時返回的結果是 9899, 不在是101個文檔,而是4 MB,我們9899個文檔沒達到4MB,所有全部返回。
說明:
MongoDB使用的是記憶體映射儲存引擎,它會把磁碟IO操作轉換成記憶體操作,如果是讀操作,記憶體中的資料起到緩衝的作用。查詢時,實現分批次返回結果,這是一個懶載入的過程,需要時才到資料庫查詢下一批結果,這會節省資源,不會浪費資源。
三、遊標的操作
我們還可以對文檔的遊標,可以隨意修改返回結果的限制、跳躍、和排序次序的功能。
1. limit
limit方法是限制遊標返回結果的數量,如下面例子:
>db.items.find().limit(5)
只返回結果5條文檔
2.sort
sort()方法來對資料進行排序,根據指定的欄位,並使用1或-1來指定排序方式是升序或降序,類似於SQL的order by。
例子:
>db.items.find({"ino":{$lt:5}}).sort({"quantity":-1})
我們查詢ino小於5,並對這結果進行排序,按quantity欄位降序。
我們可以指定多個欄位排序,例如我們先按quantity欄位降序,然後在按info升序,如下面的例子:
>db.items.find({"ino":{$lt:5}}).sort({"quantity":-1,"info":1})
我們查詢ino小於5,並對這結果進行排序,按quantity欄位降序
我們還可以跟limit()方法進行組合查詢並對結果進行排序
例子:
>db.items.find().limit(3).sort({"quantity":1})
我們先根據quantity欄位升序並返回前3條記錄,發現沒有鍵quantity(即鍵quantity值為null)的文檔排在了前面,這是在MongoDB中,當比較不同類型值BSON,MongoDB使用以下比較順序,從最低到最高:
- MinKey (internal type)
- Null
- Numbers (ints, longs, doubles)
- Symbol, String
- Object
- Array
- BinData
- ObjectId
- Boolean
- Date
- Timestamp
- Regular Expression
- MaxKey (internal type)
對於包括一個沒有索引的排序操作的查詢,伺服器必須在返回任何結果之前將所有的文檔載入到記憶體中來進行排序。
3、skip
skip方法可以跳過指定值的條數,返回剩下的條數的結果,可以跟limit()方法進行組合可以實現分頁的效果。
例子:
>db.items.find().skip(10).limit(10)
跳過第10條,從第11條開始返回,只返回10條文檔.
skip方法是跳過條數,而且是一條一條的跳過,如果集合比較大時(如書頁數很多)skip會越來越慢, 需要更多的處理器(CPU),這會影響效能。
我們可以通過一個鍵值比較有順序的來進行分頁,這樣就避免使用skip方法。
例子:
>db.items.find({"ino":{$lt:20,$gt:9}}).sort({"info":1})
四、遊標的說明
預設情況下,伺服器將自動關閉該遊標10分鐘後閑置或用戶端遍曆完結果的遊標。需要手動關閉遊標或清除遊標是,可以在查詢中使用游標指定noTimeout標記。通過 cursor.addOption(),通過這個方法,如下面的例子:
>var cursor = db.items.find().addOption(DBQuery.Option.noTimeout);
可以查看遊標資訊:
(1) 開啟的遊標的總數
(2)當前用戶端使用的遊標大小
(3)自上次重新啟動伺服器的逾時遊標數量
我們可以查看,瞭解遊標使用方式
如下面的例子:
>db.serverStatus().metrics.cursor
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。