本文章是由機器翻譯。

程式設計師雜談

使用 MongoDB 投入 NoSQL 的懷抱 (第 3 部)

Ted Neward

下載範例程式碼

我繼續透過探索測試使用我探索 MongoDB 的最後一次的時間。我說明如何啟動及停止一個的測試期間的伺服器,然後示範如何擷取交叉文件參考並討論一些這樣做的 awkwardness 背後。現在它 ’s 時間瀏覽某些更多中繼 MongoDB 功能:述詞的查詢、 彙總函數和 MongoDB.Linq 組件所提供的 LINQ 支援。我也提供一些有關裝載 MongoDB 在實際執行環境中的備忘稿。

當我們最後一筆由我們的英雄。..

空間的原因我 won’t 檢閱的前一個文件 ; 而是,您可以在 可能6 月 問題,在 msdn.microsoft.com/magazine 讀取它們線上]。在相關聯的程式碼] 配套但是,探索測試已被 fleshed 出要包含已存在的範例設定来使用的使用其中一個我喜愛的電視節目的字元資料。圖 1 顯示先前的 「 探索 」 測試,藉由重新整理程式的方式。到目前為止還不錯吧!

圖 1 的範例探索測試

[TestMethod]
        public void StoreAndCountFamilyWithOid()
        {
          var oidGen = new OidGenerator();
          var peter = new Document();
          peter["firstname"] = "Peter";
          peter["lastname"] = "Griffin";
          peter["_id"] = oidGen.Generate();

          var lois = new Document();
          lois["firstname"] = "Lois";
          lois["lastname"] = "Griffin";
          lois["_id"] = oidGen.Generate();

          peter["spouse"] = lois["_id"];
          lois["spouse"] = peter["_id"];

          var cast = new[] { peter, lois };
          var fg = db["exploretests"]["familyguy"];
          fg.Insert(cast);

          Assert.AreEqual(peter["spouse"], lois["_id"]);
          Assert.AreEqual(
            fg.FindOne(new Document().Append("_id",
              peter["spouse"])).ToString(), lois.ToString());

          Assert.AreEqual(2,
            fg.Count(new Document().Append("lastname", "Griffin")));
        }

呼叫所有舊的人員。 . .

用戶端程式碼已在先前的發行項中擷取符合特定的條件 (例如,具有 「 姓氏 」 欄位符合指定的字串或符合特定 Oid 的 「 _id 」 欄位),任一所有文件,但我 haven’t 討論如何述詞樣式查詢 (例如,「 尋找所有的文件位置 ‘ 年齡 ’] 欄位有值,高於 18 」)。 當它原來 MongoDB doesn’t 使用 SQL 樣式介面來描述要執行查詢 ; 而是,它使用 ECMAScript/JavaScript,和它事實上可以接受的預存程序類似幾乎執行篩選或彙總的資料到伺服器上的程式碼區塊。

這會提供一些 LINQ 類似] 功能甚至之前查看 Mongo.Linq 組件所支援的 LINQ 功能。 藉由指定文件中包含欄位名稱為 「 $ 位置 」 及程式碼區塊描述 ECMAScript 執行的程式碼可建立自訂的複雜的查詢:

 

[TestMethod]
        public void Where()
        {
          ICursor oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where", 
            new Code("this.gender === 'F'")));
          bool found = false;
          foreach (var d in oldFolks.Documents)
            found = true;
          Assert.IsTrue(found, "Found people");
        }

您可以看到尋找呼叫會傳回一個 ICursor] 執行個體的雖然本身 isn’t IEnumerable (can’t 使用 foreach 迴圈中的意義)、 包含 ’s 的 IEnumerable <Document> 的文件屬性。 如果查詢會傳回的資料太大一組,[ICursor 可以限制來限制] 屬性設定為 n 傳回第一個 n 的結果。

述詞的查詢語法有四個 的 [圖 2] 所示的不同方式。

圖 2 的 四種不同的述詞查詢語法

[TestMethod]
        public void PredicateQuery()
        {
          ICursor oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("age",
            new Document().Append("$gt", 18)));
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where",
            new Code("this.age > 18")));
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find("this.age > 18");
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where",
            new Code("function(x) { return this.age > 18; }")));
          Assert.AreEqual(6, CountDocuments(oldFolks));
        }

在第二個和第三個的表單 「 這個 」 永遠參照物件正在檢查。

您可以傳送任何任意命令 (也就是 ECMAScript 程式碼) 透過驅動程式到的資料庫中就實際上使用文件來傳遞查詢或命令。 因此,就例如 IMongoCollection 介面所提供的計算方法是其實只是方便周圍這個比較複雜的程式碼片段:

[TestMethod]
        public void CountGriffins()
        {
          var resultDoc = db["exploretests"].SendCommand(
            new Document()
              .Append("count", "familyguy")
              .Append("query",
                new Document().Append("lastname", "Griffin"))
            );
          Assert.AreEqual(6, (double)resultDoc["n"]);
        }

這表示任何如 「 不同 」 或 「 群組 」,MongoDB 的文件所描述的彙總作業,就例如都透過相同的機制,可存取,即使它們可能不會提出為方法上 MongoDB.Driver API。

您可以傳送任意命令之外,透過 「 特殊名稱 」 語法 「 $ eval,」 資料庫的查詢可讓一次基本上與預存程序執行針對的伺服器程式任何的碼合法 ECMAScript 區塊:

[TestMethod]
        public void UseDatabaseAsCalculator()
        {
          var resultDoc = db["exploretests"].SendCommand(
            new Document()
              .Append("$eval", 
                new CodeWScope { 
                  Value = "function() { return 3 + 3; }", 
                  Scope = new Document() }));
          TestContext.WriteLine("eval returned {0}", resultDoc.ToString());
          Assert.AreEqual(6, (double)resultDoc["retval"]);
        }

或在資料庫中直接使用所提供的 Eval 函數。 如果所 isn’t 有足夠的彈性,MongoDB 允許使用者定義函式 ECMAScript 的儲存查詢和伺服器端執行區塊期間執行的資料庫執行個體上 ECMAScript 函式加入特殊的資料庫集合 「 system.js,」 的 MongoDB 網站 上所述。

遺失的 LINQ

C# MongoDB 驅動程式也會有讓開發人員撰寫 MongoDB 用戶端程式碼,例如什麼 的 圖 3 所示的 LINQ 支援。

圖 3 的 LINQ 支援的範例

[TestMethod]
        public void LINQQuery()
        {
          var fg = db["exploretests"]["familyguy"];
          var results = 
            from d in fg.Linq() 
            where ((string)d["lastname"]) == "Brown" 
            select d;
          bool found = false;
          foreach (var d in results)
          {
            found = true;
            TestContext.WriteLine("Found {0}", d);
          }
          Assert.IsTrue(found, "No Browns found?");
        }

和追隨 MongoDB 資料庫的動態本質,與這個範例需要沒有程式碼產生,只是呼叫 Linq 返回 「 啟用 」 MongoDB LINQ 提供者的物件。 撰寫本文的同時,LINQ 的支援是相當基本,但正在改進並本文到達列印時,將會大幅提高。 專案網站的 Wiki 會文件的新功能和範例。

傳送是一個功能

以上所有就其他如果 MongoDB 要用在實際執行環境中,幾件事需要加以處理,使其較不痛苦的不良的 chaps 者必須將保持生產伺服器和執行的服務。

若要開始,伺服器處理序 (mongod.exe) 必須安裝為服務 — 在互動式桌面工作階段中執行通常不允許在實際執行伺服器上。 至該的結尾處 mongod.exe 支援是服務的安裝選項 「-安裝,」 的安裝,然後藉由服務面板或命令列來啟動的服務:「 net start MongoDB 」。但是的撰寫本文有 ’s 一個小 quirk--安裝命令中 — 它會在可執行檔路徑推斷藉由查看 [用來執行它,所以完整路徑必須指定命令列上的命令列。 這表示如果 MongoDB 安裝在 C:\Prg\mongodb,您必須安裝它,在命令提示字元 (具有系統管理權限) 與命令 C:\Prg\mongodb\bin\mongod.exe-服務安裝。

但是,任何命令列的參數例如 「-dbpath,」 必須也會顯示在這表示如果該安裝] 命令的任何設定 — 移植,資料檔案的路徑等等 — 變更,服務必須重新安裝。 幸運的是,MongoDB 支援所給定一個組態檔案選項在 「-組態 」 指令行的選項,通常最好的方法是將完整的組態檔路徑傳遞至服務安裝和執行從該處的所有其他設定:

C:\Prg\mongodb\bin\mongod.exe --config C:\Prg\mongodb\bin\mongo.cfg --install
net start MongoDB

如往常般進行測試以確保順利執行服務最簡單的方法是使用隨附 MongoDB 下載 mongo.exe 用戶端連接到它。 與伺服器進行通訊的通訊端透過用戶端,因為需要 poke 在防火牆,以允許在伺服器間的通訊所需的漏洞。

這些 Aren’t 您對於尋找的資料 Droids

就說到 MongoDB 伺服器有無安全性的存取 isn’t 可能是一個很好的事,因此保護不想要的訪客對伺服器變成主要的功能。 MongoDB 支援驗證,但安全性系統任何地方 isn’t 附近為發現與 「 大鐵 」 資料庫 (例如 SQL Server 為複雜。

通常,第一個步驟是建立資料庫的系統管理員登入 mongo.exe 用戶端與資料庫連接,和管理使用者加入管理資料庫 (資料庫含有資料的執行和管理整個 MongoDB 伺服器),如下:

> use admin
> db.addUser("dba", "dbapassword")

一旦完成這甚至在此的命令介面內的任何進一步動作需要完成在殼層中,由明確驗證的驗證的存取:

> db.authenticate("dba", "dbapassword")

現在 [DBA 就可以使用者新增到 MongoDB 資料庫變更資料庫,以及新增使用者使用相同的 addUser 呼叫前面所示:

> use mydatabase
> db.addUser("billg", "password")

當連接到 「 Mongo.Driver 透過資料庫,傳遞驗證資訊,用來建立 Mongo 物件的連接字串的一部分,並相同的驗證魔法會透明地發生:

var mongo = new Mongo("Username=billg;Password=password");

自然,密碼 shouldn’t 會直接進入程式碼的硬式編碼或公開儲存 ; 使用相同的密碼專業領域為 befits 任何資料庫為基礎的應用程式。在就其實應該儲存在組態檔中並透過 ConfigurationManager 類別擷取整個組態 (主機、 連接埠、 密碼等)。

若要修改某些程式碼到達出

定期,系統管理員將會想要查看正在執行的執行個體,來取得正在執行的伺服器的診斷資訊。MongoDB 支援 HTTP 介面的互動,連接埠數字 1000 高於它設定為使用標準的用戶端通訊的連接埠上執行。因此,因為預設 MongoDB 連接埠 27017 HTTP 介面可以找上連接埠 28017, 的 圖 4 所示。

圖 4 的 MongoDB 與互動的 HTTP 介面

這個 HTTP 介面也允許更多的 REST 樣式通訊方法,相較於在 MongoDB.Driver 和 MongoDB.Linq 原生的驅動程式 ; MongoDB 網站有完整的詳細資料,但基本上是 HTTP URL 來存取集合 ’s 內容藉由新增資料庫名稱及集合] 名稱來作為所示 的 圖 5 中分隔 [斜線],由指定。

圖 5 的 HTTP URL 的存取集合 ’s 內容

詳細上建立 REST 用戶端使用 WCF 請參閱 MSDN 文件 「 的 REST 在 Windows 通訊基礎 (WCF) 」。

從 Yoda 的 Word

MongoDB 是快速發展的產品,並將這些的文件時瀏覽 MongoDB ’s 的功能的核心部分仍保留 unexamined 的主要區域。 雖然 MongoDB isn’t SQL Server 的直接取代,它證明的區域位置傳統的 RDBMS doesn’t 也因此 fare 一可行的儲存體中的替代方法。同樣地,就像 MongoDB 是的發展,進行中,所以是 mongodb csharp 專案。  撰寫本文的同時許多新的改良功能已進入 Beta 版包括用於使用一般的物件的強型別集合的增強功能,以及大幅提升 LINQ 的支援。 隨時注意兩者。

在此同時但是,它 ’s MongoDB 到聲波辭別,並使我們注意到工作的程式設計人員可能不的開發人員 ’s 世界的其他組件的時間熟悉和應該可說是。現在,不過,快樂編碼,並記住作為很棒的 DevGuy 母片 Yoda 一旦說,「 A DevGuy 使用 [來源的知識和防禦; 永遠不會為一個劈砍 」

Ted Neward 是與 Neward 的主體 (& I) 關聯的獨立的公司,專精於 企業 Microsoft.NET Framework 和 Java 平台系統。他寫入 100 個以上的文件一個 C# MVP,INETA 喇叭和作者和 coauthor 十幾的書籍的包括 「 專業 F # 2.0 」 (Wrox 2010)。他諮詢,並定期 mentors。 ted@tedneward.com 在到達他和讀取他的部落格,在 blogs.tedneward.com

感謝至下列的技術專家來檢閱這份文件: Sam Corder 和 的 Craig Wilson