獲取數(shù)據(jù)庫(kù)
下載數(shù)據(jù)庫(kù), 解包, 運(yùn)行mongod:
連接數(shù)據(jù)庫(kù)
現(xiàn)在我們通過(guò)數(shù)據(jù)庫(kù)的shell來(lái)實(shí)際操作一下。(注意:任何編程語(yǔ)言都可以通過(guò)合適的驅(qū)動(dòng)進(jìn)行類(lèi)似的操作.只不過(guò)shell的方式更方便交互操作。)
運(yùn)行MongoDB JavaScript shell:
(默認(rèn)情況下shell將連接本機(jī)(localhost)的數(shù)據(jù)庫(kù))你會(huì)看到:
MongoDB shell version: 0.9.8
url: test
connecting to: test
type "help" for help
>
"connecting to:" 表明shell連接的數(shù)據(jù)名。要切換數(shù)據(jù)庫(kù):
輸入 help 可以看到一個(gè)簡(jiǎn)單的命令列表。
 |
給有其他數(shù)據(jù)庫(kù)經(jīng)驗(yàn)的開(kāi)發(fā)者的提示
在下面的例子中你可能會(huì)注意到,我們沒(méi)有創(chuàng)建數(shù)據(jù)庫(kù)和集。MongoDB并不用那么做。一旦你插入內(nèi)容,MongoDB會(huì)建立對(duì)應(yīng)的集和數(shù)據(jù)庫(kù)。要是查詢了不存在的集,Mongo就將其視為空的集。 |
向集中插入數(shù)據(jù)
我們建立一個(gè)測(cè)試用的集,然后插入一些數(shù)據(jù)。我們將會(huì)新建兩個(gè)對(duì)象 j 和 t , 然后將其存放在 things 集中。
下面的例子中, '>' 表示shell命令提示符
> j = { name: "mongo"};
{"name" : "mongo"}
> t = { x : 3 };
{ "x" : 3 }
> db.things.save(j);
> db.things.save(t);
> db.things.find();
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
>
注意事項(xiàng):
- 我們并沒(méi)有預(yù)先定義集。數(shù)據(jù)庫(kù)會(huì)在第一次插入操作時(shí)自動(dòng)創(chuàng)建集。
- 我們存儲(chǔ)的文檔可以擁有任意不同的結(jié)構(gòu)。事實(shí)上在本例中,文檔之間根本沒(méi)有共同的數(shù)據(jù)元素。在實(shí)際應(yīng)用中文檔通常都已相同的結(jié)構(gòu)保存在集里面。這種靈活意味著遷移或者擴(kuò)充都非常容易。幾乎不需要寫(xiě)腳本來(lái)執(zhí)行諸如“alter table”之類(lèi)的操作。
- 一旦被插入數(shù)據(jù)庫(kù),對(duì)象就被分配一個(gè)ID(要是還沒(méi)有的話)存儲(chǔ)在 _id 域中
- 你運(yùn)行上面的例子時(shí),你的ObjectID的值會(huì)有所不同。
下面再往集里面添加一些記錄:
> for( var i = 1; i < 10; i++ ) db.things.save( { x:4, j:i } );
> db.things.find();
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
has more
注意這里并沒(méi)有列出所有的文檔 - shell 會(huì)默認(rèn)顯示10個(gè)。先前已經(jīng)有兩個(gè)文檔在集里面了,所以這里只能看見(jiàn)新插入的前8個(gè)文檔。
要是想接著看結(jié)果,可以用 it 。接著上面的例子往下:
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
has more
> it
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
{"x" : 4 , "j" : 10 , "_id" : "497cf87151712cf7758fbdc6"}
通常,find()會(huì)返回一個(gè)游標(biāo)對(duì)象,但是在上面那個(gè)例子中,我們并不確定游標(biāo)是可移動(dòng)的。所以shell自動(dòng)的移動(dòng)游標(biāo),并且把初始化后的結(jié)果返回給我們,同時(shí)允許我們通過(guò)"it"命令繼續(xù)移動(dòng)游標(biāo)。
但是我們?nèi)匀豢梢灾苯邮褂糜螛?biāo),在下一部分中將討論如何這樣做。
使用查詢?cè)L問(wèn)數(shù)據(jù)
在我們對(duì)查詢進(jìn)行深入討論之前,我們先來(lái)看看如何通過(guò)一個(gè)游標(biāo)對(duì)象操作查詢結(jié)果。我們將使用簡(jiǎn)單的find()查詢函數(shù),它會(huì)返回一個(gè)集(表),并且在隨后討論如何創(chuàng)建一個(gè)具體的查詢。
在使用mongo shell的時(shí)候,為了查看所有集(表)中的數(shù)據(jù),我們需要從find()操作中返回一個(gè)游標(biāo)。
然后開(kāi)始重復(fù)相同的查詢操作,但是這次我們使用find()返回的游標(biāo),并且在while循環(huán)中移動(dòng)游標(biāo):
> var cursor = db.things.find();
> while (cursor.hasNext()) { print(tojson(cursor.next())); }
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
上述例子展示了一個(gè)游標(biāo)的使用方式,hasNext()函數(shù)返回當(dāng)前的document對(duì)象后面是否還有數(shù)據(jù),而next()函數(shù)則返回一個(gè)document對(duì)象。同時(shí)我們還使用了內(nèi)嵌的tojson()函數(shù)來(lái)把document的對(duì)象變成JSON數(shù)據(jù)格式。
這個(gè)shell是Javascript的,所以這里還可以享用其語(yǔ)言本身的特性:可以對(duì)游標(biāo)調(diào)用 forEach 。還拿上面的例子來(lái)說(shuō),直接在游標(biāo)處將循環(huán)用 forEach() 換掉了:
> db.things.find().forEach( function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
在{{forEach()}}里必須定義對(duì)游標(biāo)中的每一個(gè)文檔的操作函數(shù)。
在 mongo shell中,也可以把游標(biāo)當(dāng)作數(shù)組處理:
> var cursor = db.things.find();
> print (tojson(cursor[4]));
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
當(dāng)這樣使用游標(biāo)時(shí),注意這會(huì)將最大訪問(wèn)數(shù)據(jù)(上面的例子中的cursor[4])以下的所有數(shù)據(jù)都同時(shí)加載到內(nèi)存中。這對(duì)大結(jié)果非常不合適,會(huì)導(dǎo)致內(nèi)存不夠用的。返回結(jié)果數(shù)量很大時(shí),游標(biāo)應(yīng)該作為迭代器使用。
In addition to array-style access to a cursor, you may also convert the cursor to a true array:
除了用數(shù)組的風(fēng)格來(lái)操作游標(biāo),也可以干脆將游標(biāo)轉(zhuǎn)換程真正的數(shù)組:
> var arr = db.things.find().toArray();
> arr[5];
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
請(qǐng)注意這種數(shù)組特性是[]特有的,并不是所有的驅(qū)動(dòng)都支持。
MongoDB游標(biāo)并不做快照。如果你或者別人在你查詢時(shí),確切的說(shuō)從第一次到最后一次調(diào)用 {{next}}之間,對(duì)數(shù)據(jù)進(jìn)行了修改,那么修改可能被返回,也可能不返回。要是想做快照查詢的話得使用互斥鎖。
h3. 定制查詢結(jié)果
現(xiàn)在我們知道了如何使用查詢返回的游標(biāo)對(duì)象,下面看看如何通過(guò)修改查詢來(lái)定制結(jié)果。
通常,可以通過(guò)創(chuàng)建一種鍵值相匹配的”query documents”來(lái)實(shí)現(xiàn)這個(gè)方式。
這些用實(shí)例更能說(shuō)明問(wèn)題。在下面的例子里,我們將給出SQL查詢的例子,并且同時(shí)利用MongDB的 [mongo shell|mongo - The Interactive Shell] 實(shí)現(xiàn)查詢,通過(guò)這種方式進(jìn)行查詢對(duì)于MongoDB來(lái)說(shuō)是必要的,而且你也會(huì)發(fā)現(xiàn)其在任何語(yǔ)言環(huán)境中的便利性。
{code:title=SELECT * FROM things WHERE name="mongo"}> db.things.find({name:"mongo"}).forEach(function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
>
> db.things.find({x:4}).forEach(function(x) { print(tojson(x));});
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
查詢表達(dá)式本身就是一個(gè)document對(duì)象,如果是一個(gè)類(lèi)似于{a:A, b:B, …}的document查詢對(duì)象,則表示”where a=A and b=B and…”,更多關(guān)于查詢的用法,在 Mongo開(kāi)發(fā)者指南 的 查詢與游標(biāo) 章節(jié)中。
MongoDB也允許您返回一個(gè)”部分document對(duì)象”,也就是返回一個(gè)數(shù)據(jù)庫(kù)中存儲(chǔ)的document的子集。您只要通過(guò)使用find()函數(shù)的第二個(gè)參數(shù)就可以做到這一點(diǎn)。
例如,我們?cè)谏弦粋€(gè) find({x:4}) 的例子中,加一個(gè)函數(shù),就能夠只返回j列的數(shù)據(jù)了:
> db.things.find({x:4}, {j:true}).forEach(function(x) { print(tojson(x));});
{"j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
Note that the "_id" field is always returned.
需要注意的是"_id"列是每次都要被返回的。
findOne() -
為了方便起見(jiàn),mongo shell(和其他驅(qū)動(dòng))能避免讓你編程處理游標(biāo),你只需要通過(guò)findOne()函數(shù)就能獲得一個(gè)文檔。findOne()和find()使用相同的參數(shù),但是它不返回游標(biāo),而是從數(shù)據(jù)庫(kù)中返回第一個(gè)檔,或者沒(méi)有匹配條目時(shí)返回null。
例如,我們可以通過(guò)很多種方式檢索一個(gè)名稱為’mongo’的document,包括在游標(biāo)中調(diào)用next()函數(shù)(當(dāng)然,要驗(yàn)證完是否為null之后),或者把游標(biāo)看做一個(gè)數(shù)組然后訪問(wèn)數(shù)組的[0]下標(biāo)元素。
無(wú)論采用何種方式,findOne()函數(shù)還是既方便又高效的:
> var mongo = db.things.findOne({name:"mongo"});
> print(tojson(mongo));
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
>
如果只從數(shù)據(jù)庫(kù)返回一個(gè)對(duì)象,這個(gè)方式是更加方便的,并且在數(shù)據(jù)庫(kù)和網(wǎng)絡(luò)傳輸上有更少的工作需要來(lái)做。這種方式等價(jià)于find({name:"mongo"}).limit(1)。
使用 limit()
通過(guò) limit() 方法可以指定返回結(jié)果的最大數(shù)量,這樣就能控制查詢結(jié)果的大小了。
非常推薦使用這種方式,可以提高性能,因?yàn)檫@樣減少了數(shù)據(jù)庫(kù)的工作量,也減少了網(wǎng)絡(luò)中的數(shù)據(jù)流量。舉個(gè)例子:
> db.things.find().limit(3);
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
>
posted on 2010-06-23 15:40
Derek.Guo 閱讀(1583)
評(píng)論(1) 編輯 收藏 所屬分類(lèi):
NoSqlDB