獲取數據庫
下載數據庫, 解包, 運行mongod:
連接數據庫
現在我們通過數據庫的shell來實際操作一下。(注意:任何編程語言都可以通過合適的驅動進行類似的操作.只不過shell的方式更方便交互操作。)
運行MongoDB JavaScript shell:
(默認情況下shell將連接本機(localhost)的數據庫)你會看到:
MongoDB shell version: 0.9.8
url: test
connecting to: test
type "help" for help
>
"connecting to:" 表明shell連接的數據名。要切換數據庫:
輸入 help 可以看到一個簡單的命令列表。
 |
給有其他數據庫經驗的開發者的提示
在下面的例子中你可能會注意到,我們沒有創建數據庫和集。MongoDB并不用那么做。一旦你插入內容,MongoDB會建立對應的集和數據庫。要是查詢了不存在的集,Mongo就將其視為空的集。 |
向集中插入數據
我們建立一個測試用的集,然后插入一些數據。我們將會新建兩個對象 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"}
>
注意事項:
- 我們并沒有預先定義集。數據庫會在第一次插入操作時自動創建集。
- 我們存儲的文檔可以擁有任意不同的結構。事實上在本例中,文檔之間根本沒有共同的數據元素。在實際應用中文檔通常都已相同的結構保存在集里面。這種靈活意味著遷移或者擴充都非常容易。幾乎不需要寫腳本來執行諸如“alter table”之類的操作。
- 一旦被插入數據庫,對象就被分配一個ID(要是還沒有的話)存儲在 _id 域中
- 你運行上面的例子時,你的ObjectID的值會有所不同。
下面再往集里面添加一些記錄:
> 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
注意這里并沒有列出所有的文檔 - shell 會默認顯示10個。先前已經有兩個文檔在集里面了,所以這里只能看見新插入的前8個文檔。
要是想接著看結果,可以用 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()會返回一個游標對象,但是在上面那個例子中,我們并不確定游標是可移動的。所以shell自動的移動游標,并且把初始化后的結果返回給我們,同時允許我們通過"it"命令繼續移動游標。
但是我們仍然可以直接使用游標,在下一部分中將討論如何這樣做。
使用查詢訪問數據
在我們對查詢進行深入討論之前,我們先來看看如何通過一個游標對象操作查詢結果。我們將使用簡單的find()查詢函數,它會返回一個集(表),并且在隨后討論如何創建一個具體的查詢。
在使用mongo shell的時候,為了查看所有集(表)中的數據,我們需要從find()操作中返回一個游標。
然后開始重復相同的查詢操作,但是這次我們使用find()返回的游標,并且在while循環中移動游標:
> 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"}
>
上述例子展示了一個游標的使用方式,hasNext()函數返回當前的document對象后面是否還有數據,而next()函數則返回一個document對象。同時我們還使用了內嵌的tojson()函數來把document的對象變成JSON數據格式。
這個shell是Javascript的,所以這里還可以享用其語言本身的特性:可以對游標調用 forEach 。還拿上面的例子來說,直接在游標處將循環用 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()}}里必須定義對游標中的每一個文檔的操作函數。
在 mongo shell中,也可以把游標當作數組處理:
> var cursor = db.things.find();
> print (tojson(cursor[4]));
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
當這樣使用游標時,注意這會將最大訪問數據(上面的例子中的cursor[4])以下的所有數據都同時加載到內存中。這對大結果非常不合適,會導致內存不夠用的。返回結果數量很大時,游標應該作為迭代器使用。
In addition to array-style access to a cursor, you may also convert the cursor to a true array:
除了用數組的風格來操作游標,也可以干脆將游標轉換程真正的數組:
> var arr = db.things.find().toArray();
> arr[5];
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
請注意這種數組特性是[]特有的,并不是所有的驅動都支持。
MongoDB游標并不做快照。如果你或者別人在你查詢時,確切的說從第一次到最后一次調用 {{next}}之間,對數據進行了修改,那么修改可能被返回,也可能不返回。要是想做快照查詢的話得使用互斥鎖。
h3. 定制查詢結果
現在我們知道了如何使用查詢返回的游標對象,下面看看如何通過修改查詢來定制結果。
通常,可以通過創建一種鍵值相匹配的”query documents”來實現這個方式。
這些用實例更能說明問題。在下面的例子里,我們將給出SQL查詢的例子,并且同時利用MongDB的 [mongo shell|mongo - The Interactive Shell] 實現查詢,通過這種方式進行查詢對于MongoDB來說是必要的,而且你也會發現其在任何語言環境中的便利性。
{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"}
>
查詢表達式本身就是一個document對象,如果是一個類似于{a:A, b:B, …}的document查詢對象,則表示”where a=A and b=B and…”,更多關于查詢的用法,在 Mongo開發者指南 的 查詢與游標 章節中。
MongoDB也允許您返回一個”部分document對象”,也就是返回一個數據庫中存儲的document的子集。您只要通過使用find()函數的第二個參數就可以做到這一點。
例如,我們在上一個 find({x:4}) 的例子中,加一個函數,就能夠只返回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() -
為了方便起見,mongo shell(和其他驅動)能避免讓你編程處理游標,你只需要通過findOne()函數就能獲得一個文檔。findOne()和find()使用相同的參數,但是它不返回游標,而是從數據庫中返回第一個檔,或者沒有匹配條目時返回null。
例如,我們可以通過很多種方式檢索一個名稱為’mongo’的document,包括在游標中調用next()函數(當然,要驗證完是否為null之后),或者把游標看做一個數組然后訪問數組的[0]下標元素。
無論采用何種方式,findOne()函數還是既方便又高效的:
> var mongo = db.things.findOne({name:"mongo"});
> print(tojson(mongo));
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
>
如果只從數據庫返回一個對象,這個方式是更加方便的,并且在數據庫和網絡傳輸上有更少的工作需要來做。這種方式等價于find({name:"mongo"}).limit(1)。
使用 limit()
通過 limit() 方法可以指定返回結果的最大數量,這樣就能控制查詢結果的大小了。
非常推薦使用這種方式,可以提高性能,因為這樣減少了數據庫的工作量,也減少了網絡中的數據流量。舉個例子:
> 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)
評論(1) 編輯 收藏 所屬分類:
NoSqlDB