1. 程式人生 > >MongoDB之——基於Shell命令列操作記錄

MongoDB之——基於Shell命令列操作記錄

一、插入記錄

下面我們來建立一個 test 的集合並寫入一些資料. 建立兩個物件 j 和 t , 並儲存到集合中去.
在例子裡 “>” 來表示是 shell 輸入提示符

> j = { name : "mongo" };
{"name" : "mongo"}
> t = { x : 3 };
{ "x" : 3 }
> db.things.save(j);
> db.things.save(t);
> db.things.find();
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }
{ "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }
>

有幾點需要注意一下:
1)不需要預先建立一個集合. 在第一次插入資料時候會自動建立.
2)在文件中其實可以儲存任何結構的資料, 當然在實際應用我們儲存的還是相同型別文件的集合. 這個特性其實可以在應用裡很靈活, 你不需要類似 alter table 語句來修改你的資料結構
3)每次插入資料時候集合中都會有一個 ID, 名字叫 _id.
下面再加點資料:

> for( var i = 1; i < 10; i++ ) db.things.save( { x:4, j:i } ); > db.things.find();
{"name" : "mongo" , "_id" : ObjectId("497cf60751712cf7758fbdbb")}
{"x" : 3 , "_id" : ObjectId("497cf61651712cf7758fbdbc")}
{"x" : 4 , "j" : 1 , "_id" : ObjectId("497cf87151712cf7758fbdbd")}
{"x" : 4 , "j" : 2 , "_id" : ObjectId("497cf87151712cf7758fbdbe")}
{"x" : 4 , "j" : 3 , "_id" : ObjectId("497cf87151712cf7758fbdbf")}
{"x" : 4 , "j" : 4 , "_id" : ObjectId("497cf87151712cf7758fbdc0")}
{"x" : 4 , "j" : 5 , "_id" : ObjectId("497cf87151712cf7758fbdc1")}
{"x" : 4 , "j" : 6 , "_id" : ObjectId("497cf87151712cf7758fbdc2")}
{"x" : 4 , "j" : 7 , "_id" : ObjectId("497cf87151712cf7758fbdc3")}
{"x" : 4 , "j" : 8 , "_id" : ObjectId("497cf87151712cf7758fbdc4")}
請注意一下, 這裡迴圈次數是 10, 但是隻顯示到第 8 條, 還有 2 條資料沒有顯示. 如果想繼續查詢下面的資料只需要使用”it”命令, 就會繼續顯示下面的資料:
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }
has more
> it
{ "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }
{ "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }
從技術上講 find() 返回一個遊標物件. 但在上面的例子裡, 並沒有拿到一個遊標的以 shell 自動遍歷遊標, 返回一個初始化的 set, 並允許我們繼續用 it 迭代輸出

二、查詢記錄

1、普通查詢

在沒有深入查詢之前, 我們先看看怎麼從一個查詢中返回一個遊標物件. 可以簡單的通過find() 來查詢, 他返回一個任意結構的集合. 如果實現特定的查詢稍後講解.實現上面同樣的查詢, 然後通過 while 來輸出:
> 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 }
上面的例子顯示了遊標風格的迭代輸出. hasNext() 函式告訴我們是否還有資料, 如果有則可以呼叫 next() 函式.當我們使用的是 JavaScript shell, 可以用到 JS 的特性, forEach 就可以輸出遊標了. 下面的例子就是使用 forEach() 來迴圈輸出: forEach() 必須定義一個函式供每個遊標元素呼叫.
> 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 裡, 我們也可以把遊標當作陣列來用:
> var cursor = db.things.find();
> printjson(cursor[4]);
{ "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }
使用遊標時候請注意佔用記憶體的問題, 特別是很大的遊標物件, 有可能會記憶體溢位. 所以應該用迭代的方式來輸出. 下面的示例則是把遊標轉換成真實的陣列型別:
> var arr = db.things.find().toArray();
> arr[5];
{ "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }
請注意這些特性只是在 MongoDB shell 裡使用, 而不是所有的其他應用程式驅動都支援.MongoDB 遊標物件不是沒有快照,如果有其他使用者在集合裡第一次或者最後一次呼叫next(), 你可能得不到遊標裡的資料. 所以要明確的鎖定你要查詢的遊標

2、條件查詢

到這裡我們已經知道怎麼從遊標裡實現一個查詢並返回資料物件, 下面就來看看怎麼根據指定的條件來查詢.下面的示例就是說明如何執行一個類似 SQL 的查詢, 並演示了怎麼在 MongoDB 裡實現. 這是在 MongoDB shell 裡查詢, 當然你也可以用其他的應用程式驅動或者語言來實現:
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, … } 類似 “where a==A and b==B and …” .上面顯示的是所有的元素, 當然我們也可以返回特定的元素, 類似於返回表裡某欄位的值,只需要在 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 }

3、findOne()語法

為了方便考慮, MongoDB shell 避免遊標可能帶來的開銷, 提供一個 findOne() 函式. 這個函式和 find() 函式一樣, 不過它返回的是遊標裡第一條資料, 或者返回 null,即空資料.作為一個例子, name=”mongo” 可以用很多方法來實現, 可以用 next() 來循環遊標或者當做陣列返回第一個元素.
但是用 findOne() 方法則更簡單和高效:
> printjson(db.things.findOne({name:"mongo"}));
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }

4、通過 limit 限制結果集數量

如果需要限制結果集的長度, 那麼可以呼叫 limit 方法.這是強烈推薦解決效能問題的方法, 就是通過限制條數來減少網路傳輸, 例如:
> db.things.find().limit(3);
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }
{ "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }
{ "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }

三、修改記錄

將 name 是 mongo 的記錄的 name 修改為 mongo_new
> db.things.update({name:"mongo"},{$set:{name:"mongo_new"}});

我們來查詢一下是否改過來了

> db.things.find();
{ "_id" : ObjectId("4faa9e7dedd27e6d86d86371"), "x" : 3 }
{ "_id" : ObjectId("4faa9e7bedd27e6d86d86370"), "name" : "mongo_new" }

四、刪除記錄

將使用者 name 是 mongo_new 的記錄從集合 things 中刪除
> db.things.remove({name:"mongo_new"});
> db.things.find();
{ "_id" : ObjectId("4faa9e7dedd27e6d86d86371"), "x" : 3 }
經驗證,該記錄確實被刪除了