db.collection.find()可以實現(xiàn)根據(jù)條件查詢和指定使用投影運算符返回的字段省略此參數(shù)返回匹配文檔中的所有字段。并返回到匹配文檔的游標,可以隨意修改查詢限制、跳躍、和排序順序的功能。
二、db.collection.findOne ()
db.collection. findOne ()返回滿足指定查詢條件的文檔。如果多個文檔滿足查詢,該方法返回第一個文檔,根據(jù)自然順序返回文件在磁盤上的順序,在覆蓋的集合中,自然順序與插入順序相同。
語法:
- db.collection.findOne(query, projection)
參數(shù) | 類型 | 描述 |
query | document | 可選. 使用查詢操作符指定查詢條件 |
projection | document | 指定使用投影運算符返回的字段省略此參數(shù)返回匹配文檔中的所有字段 |
Projection語法:
- { field1: <boolean>, field2: <boolean> ... }
說明:
1或者true表示返回字段
0或者false表示不返回該字段
先插入數(shù)據(jù)
- >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"})
我們執(zhí)行db.orders.findOne()時,只返回第一條記錄
例子:
- <span style="font-size:18px;"> >db.orders.findOne({"date":"2015-07-02"})</span>
二、游標的遍歷
db.collection.find()可以實現(xiàn)根據(jù)條件查詢和指定使用投影運算符返回的字段省略此參數(shù)返回匹配文檔中的所有字段。并返回到匹配文檔的游標,可以隨意修改查詢限制、跳躍、和排序順序的功能。
1、我們先通過JavaScript腳本向集合中填充10000條文檔,然后執(zhí)行db.collection.find()執(zhí)行查詢文檔
- > 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()執(zhí)行查詢文檔時,發(fā)現(xiàn)Mongo shell如果沒有分配給一個使用var關鍵字的變量迭代數(shù)據(jù)時,光標自動迭代前20個文檔的結果返回。
輸入“it”后會顯示后二十條的數(shù)據(jù)。
2、你可以使用DBQuery.shellbatchsize改變迭代次數(shù)(每頁就顯示10條記錄)
例子:
- >DBQuery.shellBatchSize = 10
現(xiàn)在光標自動迭代前10個文檔的結果返回
3、我們定義一個變量來保存這個游標
例子:
- > var cursor=db.items.find()
用一個變量來保存游標,不會自動輸出數(shù)據(jù)的,需要我們自己實現(xiàn)這個查詢結果的游標進行遍歷。
4、對游標進行遍歷
- >var cursor=db.items.find()
- >while(cursor.hasNext()){
- var doc = cursor.next();
- printjson(doc);
- };
或者
forEach()循環(huán)遍歷:
- >cursor.forEach( function(doc) { printjson(doc);});
當你遍歷游標到返回的批處理結束,如果有更多的結果,cursor.next()將執(zhí)行更多的操作來獲取下一批。
MongoDB服務器返回的查詢結果, 當調用cursor.hasNext()時,MongoDB批量的大小不會超過最大BSON文檔大小,然而對于大多數(shù)查詢,第一批返回101文檔或足夠的文件超過1 MB,后續(xù)的批大小為4 MB。如果第一批是返回101個文檔時,遍歷完時,執(zhí)行hasNext,會到數(shù)據(jù)庫查詢結果,直到所有結果都被返回,游標才會結關閉。
我們可以通過可以使用objsleftinbatch()方法來查看,每次返回文檔數(shù)量或者大小,如下面的例子:
- >var cursor=db.items.find()
- >cursor .objsLeftInBatch();
當我們剛執(zhí)行查詢時,執(zhí)行cursor .objsLeftInBatch();方法會顯示101 ,這說明第一批返回101文檔(101文檔沒超過1MB)
我們遍歷完101個文檔時,當我們執(zhí)行cursor.hasNext()時,第二批會在返回101文檔嗎?
我們先遍歷完101個文檔,如下面的例子:
- >for(vari=0;i<101;i++){
- var doc = cursor.next();
- printjson(doc);
- }
這時我們迭代完第一批返回的結果,我們在執(zhí)行cursor.hasNext();時,會到數(shù)據(jù)庫查詢下一批結果,我們objsLeftInBatch方法查看返回文檔大小,如下面的例子:
- >cursor.hasNext();
- >cursor .objsLeftInBatch();
這時返回的結果是 9899, 不在是101個文檔,而是4 MB,我們9899個文檔沒達到4MB,所有全部返回。
說明:
MongoDB使用的是內存映射存儲引擎,它會把磁盤IO操作轉換成內存操作,如果是讀操作,內存中的數(shù)據(jù)起到緩存的作用。查詢時,實現(xiàn)分批次返回結果,這是一個懶加載的過程,需要時才到數(shù)據(jù)庫查詢下一批結果,這會節(jié)省資源,不會浪費資源。
三、游標的操作
我們還可以對文檔的游標,可以隨意修改返回結果的限制、跳躍、和排序順序的功能。
1. limit
limit方法是限制游標返回結果的數(shù)量,如下面例子:
- >db.items.find().limit(5)
只返回結果5條文檔
2.sort
sort()方法來對數(shù)據(jù)進行排序,根據(jù)指定的字段,并使用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})
我們先根據(jù)quantity字段升序并返回前3條記錄,發(fā)現(xiàn)沒有鍵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方法可以跳過指定值的條數(shù),返回剩下的條數(shù)的結果,可以跟limit()方法進行組合可以實現(xiàn)分頁的效果。
例子:
- >db.items.find().skip(10).limit(10)
跳過第10條,從第11條開始返回,只返回10條文檔.
skip方法是跳過條數(shù),而且是一條一條的跳過,如果集合比較大時(如書頁數(shù)很多)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) 打開的游標的總數(shù)
(2)當前客戶端使用的游標大小
(3)自上次重新啟動服務器的超時游標數(shù)量
我們可以查看,了解游標使用情況
如下面的例子:
- >db.serverStatus().metrics.cursor