4.6.1 普通查詢 在沒(méi)有深入查詢之前, 我們先看看怎么從一個(gè)查詢中返回一個(gè)游標(biāo)對(duì)象. 可以簡(jiǎn)單的通過(guò) find() 來(lái)查詢, 他返回一個(gè)任意結(jié)構(gòu)的集合. 如果實(shí)現(xiàn)特定的查詢稍后講解. 實(shí)現(xiàn)上面同樣的查詢, 然后通過(guò) while 來(lái)輸出: > var cursor = db.things.find(); > while (cursor.hasNext()) printjson(cursor.next()); { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" } { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 } { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 } { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 } { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 } |
上面的例子顯示了游標(biāo)風(fēng)格的迭代輸出. hasNext() 函數(shù)告訴我們是否還有數(shù)據(jù), 如果有則可以調(diào)用 next() 函數(shù). 當(dāng)我們使用的是 JavaScript shell, 可以用到JS的特性, forEach 就可以輸出游標(biāo)了. 下面的例子就是使用 forEach() 來(lái)循環(huán)輸出: forEach() 必須定義一個(gè)函數(shù)供每個(gè)游標(biāo)元素調(diào)用. > db.things.find().forEach(printjson); { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" } { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 } { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 } { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 } { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 } |
在 MongoDB shell 里, 我們也可以把游標(biāo)當(dāng)作數(shù)組來(lái)用: > var cursor = db.things.find(); > printjson(cursor[4]); { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 } |
使用游標(biāo)時(shí)候請(qǐng)注意占用內(nèi)存的問(wèn)題, 特別是很大的游標(biāo)對(duì)象, 有可能會(huì)內(nèi)存溢出. 所以應(yīng)該用迭代的方式來(lái)輸出. 下面的示例則是把游標(biāo)轉(zhuǎn)換成真實(shí)的數(shù)組類(lèi)型: > var arr = db.things.find().toArray(); > arr[5]; { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 } |
請(qǐng)注意這些特性只是在MongoDB shell里使用, 而不是所有的其他應(yīng)用程序驅(qū)動(dòng)都支持. MongoDB 游標(biāo)對(duì)象不是沒(méi)有快照,如果有其他用戶在集合里第一次或者最后一次調(diào)用 next(), 你可能得不到游標(biāo)里的數(shù)據(jù). 所以要明確的鎖定你要查詢的游標(biāo). 4.6.2 條件查詢到這里我們已經(jīng)知道怎么從游標(biāo)里實(shí)現(xiàn)一個(gè)查詢并返回?cái)?shù)據(jù)對(duì)象, 下面就來(lái)看看怎么根據(jù)指定的條件來(lái)查詢. 下面的示例就是說(shuō)明如何執(zhí)行一個(gè)類(lèi)似SQL的查詢, 并演示了怎么在 MongoDB 里實(shí)現(xiàn). 這是在MongoDB shell里查詢, 當(dāng)然你也可以用其他的應(yīng)用程序驅(qū)動(dòng)或者語(yǔ)言來(lái)實(shí)現(xiàn): SELECT * FROM things WHERE name="mongo" | > db.things.find({name:"mongo"}).forEach(printjson); { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" } |
SELECT * FROM things WHERE x=4 | > db.things.find({x:4}).forEach(printjson); { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 } { "_id" : ObjectId("4c220a42f3924d31102bd857"), "x" : 4, "j" : 2 } { "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 } { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "x" : 4, "j" : 5 } |
查詢條件是 { a:A, b:B, … } 類(lèi)似 “where a==A and b==B and …”. 上面顯示的是所有的元素, 當(dāng)然我們也可以返回特定的元素, 類(lèi)似于返回表里某字段的值, 只需要在 find({x:4}) 里指定元素的名字 SELECT j FROM things WHERE x=4 | > db.things.find({x:4}, {j:true}).forEach(printjson); { "_id" : ObjectId("4c220a42f3924d31102bd856"), "j" : 1 } { "_id" : ObjectId("4c220a42f3924d31102bd857"), "j" : 2 } { "_id" : ObjectId("4c220a42f3924d31102bd858"), "j" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd859"), "j" : 4 } { "_id" : ObjectId("4c220a42f3924d31102bd85a"), "j" : 5 } | 4.6.3 findOne()語(yǔ)法為了方便考慮, MongoDB shell避免游標(biāo)可能帶來(lái)的開(kāi)銷(xiāo), 提供一個(gè)findOne() 函數(shù). 這個(gè)函數(shù)和 find() 函數(shù)一樣, 不過(guò)它返回的是游標(biāo)里第一條數(shù)據(jù), 或者返回null,即空數(shù)據(jù). 作為一個(gè)例子, name=”mongo” 可以用很多方法來(lái)實(shí)現(xiàn), 可以用 next() 來(lái)循環(huán)游標(biāo)或者當(dāng)做數(shù)組返回第一個(gè)元素. 但是用 findOne() 方法則更簡(jiǎn)單和高效: > printjson(db.things.findOne({name:"mongo"})); { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" } | 4.6.4 通過(guò)limit限制結(jié)果集數(shù)量如果需要限制結(jié)果集的長(zhǎng)度, 那么可以調(diào)用 limit 方法. 這是強(qiáng)烈推薦解決性能問(wèn)題的方法, 就是通過(guò)限制條數(shù)來(lái)減少網(wǎng)絡(luò)傳輸, 例如: > db.things.find().limit(3); { "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" } { "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 } { "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 } |
-------------------------------------------------------------------
《MongoDB管理與開(kāi)發(fā)精要》、《Redis實(shí)戰(zhàn)》作者
ChinaUnix.net專(zhuān)家 http://cdhongwan.blog.chinaunix.net
@CD紅丸 http://weibo.com/u/2446082491 |