mongodb指南(四) - developer zone - 教程

運行mongodb

請參與快速啓動指南來啓動mongodb。


連接到數據庫

首先使用數據庫shell程序來操作數據庫。(我們同樣可以使用任何語言的驅動來做類似的操作。shell程序可以很方便的進行交互和管理。)

這樣啓動mongodb JavaScript shell:

# 'mongo' is shell binary. exact location might vary depending on
# installation method and platform
$ bin/mongo

默認情況下shell程序會連接到本地的數據庫“test”。你將看到:

MongoDB shell version: <whatever>
url: test
connecting to: test
type "help" for help
>

"connecting to:"告訴你目前正在使用的數據庫名稱。可以這樣切換數據庫:

> use mydb
switched to db mydb

切換數據庫的use命令並不會立即創建這個數據庫-數據庫延遲到數據第一次插入的時候創建。這意味着如果你use某個數據庫,但是show dbs命令並不會將它列出來除非有數據插入。

要想查看可以使用的命令列表,可以敲入help.


動態模式(模式自由)

MongoDB像傳統的RDBMS一樣擁有數據庫、集合和索引。在一些場合(數據庫和集合)這些對象可以被隱式創建,不過一旦創建它們就存在於一個系統目錄中(db.systems.collections, db.system.indexes)。

集合中包含了(BSON)文檔。在這些文檔中是一些域。在mongodb中沒有預定義的域(對應於RDBMS中的列)。對於文檔內的域沒有任何模式要求-這些域和他們的值類型可以是任何類型。在這裏增加一列也沒有“alter table”的概念。儘管沒有這樣一個要求,但實際應用中,在一個集合中的文檔擁有相類似的結構是非常普遍的。這種靈活性意味着模式遷移和增大在實際中非常容易-很少會需要你去寫腳本做類似於“alter table”的操作。除了讓模式遷移靈活外,這種便利使得在數據庫之上做迭代開發更加容易。


向集合中插入數據

我們首先創建一個集合然後向裏面插入一些數據。我們會創建兩個對象,j和t,然後將他們保存在集合thins中。

在接下來的例子中,">"代表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 }
>

有幾點需要註明:

  • 我們沒有預先創建這個集合。在我們首次插入數據時數據庫自動創建了它。
  • 保存的文檔可以擁有不同的結構-實際上在這個例子中,這兩個文檔根本沒有任何相同的數據元素。在實際應用中,在一個集合中保存的數據通常具有相同的結構。
  • 在插入到數據庫之前,對象的域_id被賦予了一個object ID(如果還沒有這個域).
  • 當你運行上面的例子時,你的ObjectID值可能會不同。

讓我們增加更多的記錄到該集合中:

> for (var i = 1; i <= 20; i++) db.things.save({x : 4, j : i});
> db.things.find();
{ "_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 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }
{ "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }
{ "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }
{ "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }
{ "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }
{ "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }
{ "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }
has more

注意並不是所有的文檔都會顯示出來-當自動迭代一個遊標時,shell將返回數目限制在20.由於我們已經在集合中插入了2個文檔,因此我們只看到了18個新插入的文檔。


如果我們想要返回下一組結果,可以使用快捷方式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自動迭代了這個遊標,返回一組初始的結果,並允許我們使用it命令繼續迭代。

但是我們還可以直接使用cursor;在下面的章節中會討論該怎麼做。


從查詢中獲取數據

前面我們討論了任何深度的查詢,接下來我們講講如果使用查詢結果工作-一個遊標對象。我們將使用簡單的find()查詢函數,它會返回集合中的任何內容,後面會講如果創建特殊的查詢。

爲了使用mongo shell來查看集合中的所有元素,我們需要顯式的使用find()操作返回的遊標。

讓我們再做一次相同的查詢,但是這次使用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 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }
{ "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }
{ "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }
{ "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }
{ "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }
{ "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }
{ "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }
{ "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }
{ "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }

上面的例子顯示了遊標風格的迭代。hasNext()函數告訴我們是否還有文檔可以返回,next()函數則返回下一個文檔。我們還使用了內置的printjson()方法將文檔翻譯爲漂亮的JSON風格的格式。

當在JavaScript shell下面工作,我們還可以使用該語言實用的基本組件,然後對遊標調用forEach。重複上面的例子,但是對遊標不再使用while循環,而是直接使用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 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }
{ "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }
{ "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }
{ "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }
{ "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }
{ "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }
{ "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }
{ "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }
{ "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }

在forEach()的實例中,我們必須爲遊標定義一個函數,對於每一個文檔它都會被調用。

在mongo shell,你處理遊標還可以像處理數組:

> var cursor = db.things.find();
> printjson(cursor[4]);
{ "_id" : ObjectId("4c220a42f3924d31102bd858"), "x" : 4, "j" : 3 }

當以這種方式使用遊標時,注意所有的值直到訪問的最大值(上面是cursor[4])都會被同時裝載到RAM中。這對於很大的結果集是不合適的,因爲你會耗盡內存。對於任何返回大量元素的查詢,遊標應當作爲迭代器來使用。

除了以數組風格來訪問遊標,你可以將遊標轉換爲一個真正的數組:

> var arr = db.things.find().toArray();
> arr[5];
{ "_id" : ObjectId("4c220a42f3924d31102bd859"), "x" : 4, "j" : 4 }

請注意這種數組特性僅適用於mongo-交互型shell,並不是所有的驅動都提供這種功能。

mongodb遊標不是快照-在你第一次和最後一次調用next()中間,遊標可能返回或者不返回你或者其他用戶在這個集合中所執行的操作。使用顯式的鎖動作來執行一個快照型的查詢。


指定查詢的返回值

現在我們已經知道了如果使用查詢返回的遊標工作,讓我們關注怎麼定製查詢去返回特定的內容。

通常的方法就是創建"查詢文檔",這個查詢文檔指出了需要匹配的鍵和值的樣式。

相比於解釋,這些更容易演示。在接下來的例子中,我們會給出SQL查詢例子,然後演示如何通過mongo shell來表達相同的查詢。這種指定查詢的方法在mongodb中是很基礎的,所以你將能在所有的驅動或者語言中找到相同的通用的功能。

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 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85b"), "x" : 4, "j" : 6 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85c"), "x" : 4, "j" : 7 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85d"), "x" : 4, "j" : 8 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85e"), "x" : 4, "j" : 9 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85f"), "x" : 4, "j" : 10 }
{ "_id" : ObjectId("4c220a42f3924d31102bd860"), "x" : 4, "j" : 11 }
{ "_id" : ObjectId("4c220a42f3924d31102bd861"), "x" : 4, "j" : 12 }
{ "_id" : ObjectId("4c220a42f3924d31102bd862"), "x" : 4, "j" : 13 }
{ "_id" : ObjectId("4c220a42f3924d31102bd863"), "x" : 4, "j" : 14 }
{ "_id" : ObjectId("4c220a42f3924d31102bd864"), "x" : 4, "j" : 15 }
{ "_id" : ObjectId("4c220a42f3924d31102bd865"), "x" : 4, "j" : 16 }
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "x" : 4, "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "x" : 4, "j" : 18 }
{ "_id" : ObjectId("4c220a42f3924d31102bd868"), "x" : 4, "j" : 19 }
{ "_id" : ObjectId("4c220a42f3924d31102bd869"), "x" : 4, "j" : 20 }

查詢表達式就是文檔本身。形如{a:A,b:B,...}的查詢文檔意思是"where a--A and b==B and...".更多關於查詢能力的信息可以參閱查詢和遊標。

MongoDB還允許只返回"部分文檔"-這些文檔僅包含數據庫中文檔元素的一個子集。

實現這個功能,你在find()查詢函數中增加第二個參數,提供一個需要返回元素列表的文檔就可以了。

爲了演示這個功能,我們使用增加一個限制僅返回”j“元素的參數來重複上一個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 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85b"), "j" : 6 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85c"), "j" : 7 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85d"), "j" : 8 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85e"), "j" : 9 }
{ "_id" : ObjectId("4c220a42f3924d31102bd85f"), "j" : 10 }
{ "_id" : ObjectId("4c220a42f3924d31102bd860"), "j" : 11 }
{ "_id" : ObjectId("4c220a42f3924d31102bd861"), "j" : 12 }
{ "_id" : ObjectId("4c220a42f3924d31102bd862"), "j" : 13 }
{ "_id" : ObjectId("4c220a42f3924d31102bd863"), "j" : 14 }
{ "_id" : ObjectId("4c220a42f3924d31102bd864"), "j" : 15 }
{ "_id" : ObjectId("4c220a42f3924d31102bd865"), "j" : 16 }
{ "_id" : ObjectId("4c220a42f3924d31102bd866"), "j" : 17 }
{ "_id" : ObjectId("4c220a42f3924d31102bd867"), "j" : 18 }
{ "_id" : ObjectId("4c220a42f3924d31102bd868"), "j" : 19 }
{ "_id" : ObjectId("4c220a42f3924d31102bd869"), "j" : 20 }

注:默認情況下"_id"域始終會返回。


findOne()-語法便利

簡便起見,mongo shell(和其他的驅動)允許通過findOne()函數僅返回一個文檔,避免了程序從頭開始處理遊標。findOne()接受與find()方法相同的參數,但是不再返回遊標,而是返回要麼數據庫中第一個符合的文檔,要麼返回null如果沒有匹配到。

作爲例子,我們檢索一個符合"name=="mongo""的文檔。除了對遊標調用next()(當然首先判斷是否爲空)或者將遊標當做數組處理讀取0th元素,還有很多方法可以使用、

無論如何,findOne()方法方便並且高效:

> printjson(db.things.findOne({name:"mongo"}));
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }

這個方法更加高效,是因爲客戶端向數據庫請求單個對象,這樣數據庫和網絡和以前相比只做少量的工作。它等效於find({name:"mogno"}).limit(1).

另外一個使用_id查詢單個文檔的例子:

> var doc = db.things.findOne({_id:ObjectId("4c2209f9f3924d31102bd84a")});
> doc
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }

使用limit()限制返回個數

你可以通過limit()函數來設定返回結果的最大個數,從而限定了查詢結果的數據大小。

由於性能的原因它是強烈推薦使用的,這樣就限定了數據庫需要做的工作,限定了需要通過網絡返回的數據量大小。例如:

> db.things.find().limit(3);
{ "_id" : ObjectId("4c2209f9f3924d31102bd84a"), "name" : "mongo" }
{ "_id" : ObjectId("4c2209fef3924d31102bd84b"), "x" : 3 }
{ "_id" : ObjectId("4c220a42f3924d31102bd856"), "x" : 4, "j" : 1 }

更多幫助

除了使用"help"命令,你還可以在db和db.whatever上面調用help去查看可用的方法。

如果你很好奇某個函數內部在做什麼,你可以輸入函數名(不要())shell會打印出源代碼,例如:

> printjson
function (x) {
print(tojson(x));
}

mongo是一個完全的JavaScript shell,因此任何JavaScript函數,語法,或者類都可以在該shell中使用。另外,mongodb也定義了一些自己的類和全局變量(如db).

你可以http://api.mongodb.org/js/在查看完整的API.








發佈了5 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章