2019 年 2 月

第 34 卷,第 2 期

本文章是由機器翻譯。

[資料點]

使用 Azure Cosmos DB 為 MongoDB 提供的 API 來探索 Azure Cosmos DB 的多模型功能

藉由Julie Lerman

Julie Lerman在上個月的資料行 (msdn.com/magazine/mt848702),和很多,在那之前,我討論的 Azure Cosmos DB 全域散發的多模型資料庫服務,其支援各種 NoSQL Api 使用不同的方式。在所有我的工作到目前為止,不過,我使用只有一個特定的 API,SQL API — 可讓您使用 SQL 查詢語言與資料互動。其中一種其他模型可讓您使用適用於 MongoDB 的大部分的工具和 Api 提供 Cosmos DB 資料庫互動。此模型也受惠於 BSON 文件格式,為精簡、 有效率及提供精簡的資料類型的編碼方式的二進位序列化格式。但是有什麼可能的單一資料庫,以透過這些和其他模型 (Cassandra、 Gremlin 和資料表) 來存取?基礎資料庫引擎,根據所謂的 atom-記錄-序列 (ARS) 資料模型,讓它以原生方式支援許多不同的 Api 和資料模型中找到答案。每個 Api 是連線到熱門 NoSQL 引擎和資料結構,例如 JSON,供您的資料互動的通訊協定相容。

請務必了解,多模型 Api 目前不是可互換。Cosmos DB 資料庫都包含在 Cosmos DB 帳戶。您可以在您 Azure 訂用帳戶中的多個 Cosmos DB 帳戶,但當您建立帳戶時,您會選取哪一個 API,您將會使用該帳戶中的資料庫。選取之後,這會是唯一的 API,您可以使用針對其資料庫。Azure 文件會使用詞彙,例如 「 目前 」 時討論過這個問題,因此預期會在某個時間點會有更多的彈性,沿著這些思考。

我一直想知道嘗試另一個 API。從 Azure 資料表儲存體的一些探索時除外 (請參閱我的 2010 年 7 月文章,網址msdn.com/magazine/ff796231),而對齊和 Azure Cosmos DB 資料表 API,我還沒有使用過其他類型的資料庫仍。MongoDB 是其中一個最常使用的 Api,讓一個我決定要調查的和我已被愉快的與我的第一探勘。  我將會分享一些功能我在這裡,了解,但請記住,這不要作為 「 取得啟動與 MongoDB 」 一文。我建議您簽出 Nuri Halperin Pluralsight 課程 (bit.ly/2SI2Vxw),其中包含初學者和專家 MongoDB 內容。您可以找到內文件,以及許多其他資源的連結。

MongoDB 支援的目標是更多開發人員和系統已經在使用 MongoDB,因為 Azure 提供許多優點。甚至還有指南來移轉將資料從現有的 MongoDB 資料庫至 Azure Cosmos DB (bit.ly/2FhzmPi)。

我才能夠了解的第一個優點是,使用 MongoDB 可讓您在開發期間使用膝上型電腦上具有資料庫的本機執行個體。雖然這可以在 Windows sql 和 MongoDB Api 使用 Cosmos DB 模擬器 (bit.ly/2sHNsAn),該模擬器只在 Windows 上執行。但您可以安裝 MongoDB,我使用 Community Edition,在各種不同的作業系統,包括 macOS。這可讓您模擬本機 Mongo DB API 驅動 Cosmos DB 資料庫的基本功能。我會先在本機運作,取得適用於 MongoDB 的了解,然後切換至 Azure 資料庫。

您可以在官方的 MongoDB 文件中找到所有支援平台的安裝指示bit.ly/2S96ywj。或者,您可以提取 Docker 映像,在 macOS、 Linux 或從 Windows 上執行 MongoDB hub.docker.com/_/mongo

完成安裝之後,您會開始使用 mongod.exe 命令的程序。除非另有指定,MongoDB 會預期您已建立的目錄 /data/db,並具有存取權限。您可以在預設位置 (例如 c:\data\db 在 Windows 或 macOS 應用程式、 程式庫及使用者資料夾所在的根資料夾中),建立這個,或將位置指定為 「 mongod"命令的參數。因為我只我在開發電腦上測試方面的知識,我會使用"sudo mongod"以確保服務具有所需的權限。預設會執行 Community Edition,在 localhost、 連接埠 27017,、 127.0.0.1: 27017。

有很多方式來與 MongoDB 互動。雖然我最感興趣C#API,我有幫助啟動盡可能接近 「 裸機 」 工作,並再轉換為其中一個 Api。如果您完全新手 MongoDB 時,您可能要開始使用它 (以及服務已安裝) 的殼層來執行一些工作,在命令列。您可以啟動殼層,只要按下"mongo"。 MongoDB 安裝三個系統資料庫: 本機、 管理和組態。在殼層中,輸入 [顯示資料庫] 以看到這些列出。

MongoDB 沒有明確的命令殼層或其他 Api 中建立新的資料庫。相反地,您使用資料庫,而第一次您將資料插入,如果不存在,它會建立。試試看使用:

use myNewDatabase

如果您之後呼叫 「 顯示資料庫 」 權限,您還不會看到 myNewDatabase。

殼層會使用"db"的捷徑,來使用目前的資料庫物件,即使實際資料庫尚不存在。

現在,您需要插入文件。您建立 JSON 和 API 會將它們儲存成 MongoDB 二進位 BSON 格式文件。以下是範例文件:

{
  firstname : "Julie",
  lastname : "Lerman"
}

但文件不直接在資料庫中;它們必須儲存在集合中。如同針對資料庫,MongoDB 會遵循相同的行為與集合:如果您要參考集合尚未存在,它會為您建立時插入-ing 該集合中的資料。因此,您可以參考新的集合,同時插入新的文件。請注意,每件事是區分大小寫。我將使用名為 MyCollection 新集合中的 insertOne 方法插入文件。傳回另一個文件,確認已插入我的文件,MongoDB 會提供使用自己的資料類型,ObjectId 我插入文件的唯一識別碼索引鍵:

> db.MyCollection.insertOne({firstname:"Julie",lastname:"Lerman"})
{
  "acknowledged" : true,
  "insertedId" : ObjectId("5c169d4f603846f26944937f")
}

現在 「 顯示資料庫 」 會在其清單中包含 myNewDatabase,而且我可以查詢使用 [尋找] 命令 collec tion 物件的資料庫。我不會傳遞任何篩選或排序參數,因此它會傳回每個文件 (在我的案例中,只有一個):

>db.MyCollection.find()
{ "_id" : ObjectId("5c169d4f603846f26944937f"), "firstname" : "Julie", 
  "lastname" : "Lerman" }

我已經大略討論了在介面的功能,但就可以開始著手。結束 mongo 殼層中輸入"exit"在提示字元。

使用 Visual Studio Code 的 Cosmos DB 延伸模組

既然您已建立新的資料庫,並完成在 shell 中的一些工作,讓我們受益於一些工具。首先,我將在 Visual Studio Code 中使用 Azure Cosmos DB 延伸模組。如果您還沒有 VS Code,將它從安裝code.visualstudio.com。從 VS Code 擴充功能] 窗格中,您可以接著安裝擴充功能。

若要開啟本機的 MongoDB 執行個體中的延伸模組,附加的資料庫帳戶上按一下滑鼠右鍵,然後選擇 [附加資料庫帳戶]。 系統會提示您選擇從 Cosmos DB Api。選取 [MongoDB]。下一個提示是之位址所在的資料庫。這會預設為 MongoDB 的預設值: mongodb://127.0.0.1:27017。連線之後,您應該可以看到在 Cosmos DB explorer 中,包括建立在 shell 中的集合和文件中所示的資料庫**[圖 1**。


[圖 1 探索 MongoDB 伺服器、 資料庫和資料

如果您要編輯開啟的文件,延伸模組會提示您更新到伺服器。這將會發生您要連接到本機或雲端資料庫。

.NET Core 應用程式中的 MongoDB

現在讓我們逐步增加另一波陷和.NET Core 應用程式中使用 MongoDB 資料庫。其中一個可用的各種驅動程式是.NET 驅動程式 (bit.ly/2BvUEFl)。最新版本,也就是 2.7、 適用於.NET Framework 4.5 和 4.6,以及.NET Core 1.0 與 2.0 (包括次要版本)。我正在使用最新的.NET Core SDK (2.2),而會先建立新的主控台專案我的資料夾中名為 MongoTest,使用 dotnet 命令列介面 (CLI) 命令:

dotnet new console

接下來,我將使用 CLI 來新增.NET 驅動程式的參考,針對 MongoDB,稱為 mongocsharpdriver,到專案:

dotnet add package mongocsharpdriver

我將建立簡單的應用程式上, 個月的模型上正在使用與活頁簿和電視節目,「 領域範圍。 」 相關的一些類別 我有兩個類別,出貨和字元:

public Ship()
{
  Crew=new List<Character>();
}
  public string Name { get; set; }
  public Guid Id { get; set; }
  public List<Character> Crew{ get; set;}
}
public class Character
{
  public string Name { get; set; }
  public string Bio {get;set;}
}

請注意,出貨具有名為 id 的 Guid依照慣例,MongoDB 會屬性產生關聯,其需要的識別碼 (_i)。字元會有任何的 id。我做了模型化決策。在內容中的出貨資料互動,我一律想要查看該貨櫃的字元。將它們儲存在一起,可讓擷取簡單。或許,不過,您正在維護字元在其他地方的更多詳細。您可以將內嵌只具有例如字元的識別碼,參考的物件:

public List<Guid> Crew{ get; set;}

但這表示需要找到它們,每當您想要的字元清單一起出貨。混合式的替代方式是加入字元,好讓我交互參照所需的 Id 屬性。做為子文件中,字元的識別碼會只是隨機的屬性。MongoDB 只有根文件需要有一個 id。但是,我決定不擔心我第一探勘的識別碼字元。

有許多模型化時進行決策。最重要的是,如果您的大腦預設為關聯式資料庫的概念,其中,您需要進行大量的關聯式資料和物件之間的轉譯,您必須停止,並考慮的文件資料庫模式和評斷其優缺點。在哪裡找到本指引適用於 NoSQL 資料庫,是很有幫助 Azure Cosmos DB 文件中的文件資料模型化: bit.ly/2kpF46A

有一些功能,以了解的識別碼。如果您未提供要出貨的 Id 屬性的值,MongoDB 會建立值,就像 SQL Server 或其他資料庫一樣。如果根文件沒有任何屬性都會對應至預存的文件的識別碼 (_i) (由慣例或您自己的對應規則),它將會失敗時嘗試序列化其中 _id 是包含的結果。

使用 [mongocsharpdriver API

.NET 驅動程式 API 開頭的 MongoClient 執行個體,而您處理至資料庫和集合和文件互動。API 會反映出一些我已經示範以殼層的概念。例如,資料庫和集合可由即時插入資料。使用新的 API 的範例如下:

private static void InsertShip () {
  var mongoClient = new MongoClient ();
  var db = mongoClient.GetDatabase ("ExpanseDatabase");
  var coll = db.GetCollection<Ship> ("Ships");
  var ship = new Ship { Name = "Donnager" };
  ship.Characters.dd(new Character { Name = "Bobbie Draper", 
    Bio="Fierce Marine"});  
  coll.InsertOne (ship);
}

我使用命令殼層中的 「 使用資料庫 」 時,我現在會呼叫 GetDatabase MongoClient 物件上。資料庫物件具有泛型 GetCollection < T > 方法。我已經指定出貨,做為類型。字串"Ships"會是在資料庫中集合的名稱。定義之後,我可以 InsertOne 或 InsertMany,就像在 shell 中。.NET API 也會提供非同步對應項目,例如 InsertOneAsync。

第一次執行 InsertShip 方法中,新的資料庫和集合所建立以及新的文件中。如果我沒有插入新的文件,而且必須只參考的資料庫和集合,不會建立即時。如同殼層中,沒有任何明確的命令,建立資料庫。

以下是在資料庫中已建立之文件:

{
  "_id": {
    "$binary": "TbKPi3+tLUK9b68lJkGaww==",
    "$type": "3"
  },
  "Name": "Donnager",
  "Characters": [
    {
      "Name": "Bobbie Draper",
      Bio: "Fierce Marine"
    }
  ]
}

不過,除此之外有趣 (對我來說),是具類型的集合 (GetCollection < 出貨 >)。MongoDB 文件描述為 「 類似於關聯式資料庫中的資料表 」 集合 (bit.ly/2QZcOcD),這是一個文件資料庫的有趣描述您可以在其中儲存隨機的不相關的文件插入集合中。儘管如此,如同"ships"集合中,輸入集合以特定的型別,並建議我要強制執行此集合中的出貨類型的結構描述。但這是集合執行個體,而不是在資料庫中的實體集合。它會通知的特定執行個體如何序列化和還原序列化的物件,假設您可以從任何物件的資料儲存成單一集合。從 3.2 版開始,MongoDB 未新增一項功能,會強制執行結構描述驗證規則,但不是預設值。

我可以使用相同的船隻集合的其他型別:

var collChar = db.GetCollection<SomeOtherTypeWithAnId> ("Ships");

不過,這樣會建立問題,它會擷取資料時。您必須識別集合中的文件類型的方法。如果您閱讀有關 Cosmos DB 提供者 (這會使用 SQL API) 的 EF core 的上個月的文章,您可能還記得當 EF Core 會將文件插入 Cosmos DB,它會新增鑑別子屬性,因此您永遠都可以確定輸入文件的內容對齊。您可以執行相同的 MongoDB API,但是這樣做的駭客因為 MongoDB 使用型別來指定物件繼承的鑑別子 (bit.ly/2sbHvgA)。我已新增新的類別,繼承自 [出貨的 DecommissionedShip:

public class DecomissionedShip : Ship {
  public DateTime Date { get; set; }
}

此 API 具有名為 BsonClassMap 用來指定自訂的對應,包括其 SetDiscriminatorIsRequired 方法的類別。根據預設,這會插入類別名稱。因為您將會覆寫預設對應,您需要在自動對應方法中,也將新增。

我已新增新的方法,ApplyMappings,到 program.cs,並為 Main 方法的第一行呼叫它。具體來說,這會指示要新增出貨 」 和 「 DecommissionedShip 鑑別子的 API:

private static void ApplyMappings () {
    BsonClassMap.RegisterClassMap<Ship> (cm => {
      cm.AutoMap ();
      cm.SetDiscriminatorIsRequired (true);
    });
    BsonClassMap.RegisterClassMap<DecommissionedShip> (cm => {
      cm.AutoMap ();
      cm.SetDiscriminatorIsRequired (true);
    });
  }

我已修改另外建立新的 DecommissionedShip InsertShip 方法。因為它繼承自 [出貨,我可以使用單一的出貨集合執行個體和其 InsertMany 命令,將這兩個發行至資料庫:

var decommissionedShip=new DecommissionedShip{Name="Canterbury", 
  Date=new DateTime(2350,1,1)};
coll.InsertMany(new[]{ship,decommissionedShip});

提供集合中插入兩份文件,而且各有鑑別子新增為屬性 「 _t。 」 以下是 DecommissionedShip:

{
  "_id": {
    "$binary": "D1my7H9MrkmGzzJGSHOZfA==",
    "$type": "3"
  },
  "_t": "DecommissionedShip",
  "Name": "Canterbury",
  "Characters": [],
  "Date": {
    "$date": "2350-01-01T05:00:00.000Z"
  }
}

當擷取集合中的資料型別要出貨,如這個 GetShip 方法所示:

private static void GetShips ()
{
  var coll = db.GetCollection<Ship> ("Ships");
  var ships = coll.AsQueryable ().ToList ();
}

讀取鑑別子 API,並會具體化的出貨 」 和 「 DecommissionedShip 物件所有的資料保持不變,包括指派給 DecommissionedShip 的日期。

對應的另一個路徑是使用 BsonDocument 輸入不相依於特定類型的集合物件。核取 [我的部落格文章: 「 使用 MongoDB 的一些編碼模式C#API 」,以查看如何使用 BsonDocuments,以及如何封裝更容易閱讀的程式碼的 MongoClient、 資料庫和集合。

使用 LINQ 進行查詢

您可以使用 API 方法或 LINQ 使用.NET API 來擷取文件。API 會使用一個非常豐富尋找方法 (類似於殼層的 find 方法),可傳回一個資料指標。您可以將其傳入篩選條件、 專案屬性和傳回物件使用其執行或彙總的方法之一 — 許多這看起來像 LINQ 方法。.NET API Find 方法需要的篩選,因此若要取得所有文件,您可以篩選在新的 (空的) BsonDocument,也就是篩選條件比對任何文件。Linq,您必須將轉換集合的 IQueryable (使用 AsQueryable()),然後使用熟悉的 LINQ 方法來篩選、 排序和執行。如果您未包含,或在類別中對應的識別碼 (_i) 屬性,您必須使用投影邏輯來將之列入考量,因為它會從查詢傳回。您可以參考文件或其他文件 (例如一系列好用的在 Peter Mbanugo bit.ly/2Lqqw2J) 若要深入了這些詳細資料。

切換到 Azure Cosmos DB

您用過出您的持續性邏輯,在本機針對 MongoDB 執行個體之後,最後您需要將它移到雲端架構的 Cosmos DB。Visual Studio Code 的 Azure Cosmos DB 延伸模組可讓您輕鬆地建立新的 Cosmos DB 帳戶,如果您還沒有帳戶,雖然您可能會想要調整其設定,在入口網站。如果您使用 Visual Studio Cloud Explorer 的 VS2017 延伸具有功能進行瀏覽,但不是需要建立資料庫,因此在此情況下您要使用 Azure CLI 或入口網站中運作。

以下是如何您可以從頭開始建立的新執行個體使用 Azure Cosmos DB API for MongoDB 使用 VS Code 延伸模組。

首先,您必須連接到您的 Azure 訂用帳戶的 VS Code。這需要 Azure 帳戶延伸模組 (bit.ly/2k1phdp),這,安裝之後,可協助您連接。而且一旦連接之後,Cosmos DB 延伸模組會顯示您的訂用帳戶和任何現有的資料庫。使用 MongoDB 本機連接所示**[圖 1**,您可以切入您 Cosmos DB 帳戶、 資料庫、 集合和文件 (Cosmos DB 條款,這些容器和項目)。若要建立全新的帳戶,以滑鼠右鍵按一下頂端的 [總管] 中的延伸模組的加號。如我稍早,將會類似於建立本機的 MongoDB 資料庫中,工作流程。系統會提示您輸入帳戶名稱。我將使用 datapointsmongodbs。接下來,從可用的 Api 中選擇 [MongoDB 並建立新的 Azure 資源,或選擇現有的帳戶將繫結。我會建立一個新,所以我可以完全刪除的資源和測試資料庫所需。在此之後,您必須從裝載它的所在資料中心區域中選取。我會住在美國東部的美國,因此我將挑選美國東部位置。假設 Cosmos DB 是全域的資料庫,您可以控制使用的區域,在入口網站或其他應用程式,但我不需要我們的示範。此時,您必須建立帳戶之後稍候幾分鐘的時間。

新的帳戶建立之後,它會顯示在 [總管]。以滑鼠右鍵按一下帳戶,然後選取 [複製連接字串] 選項。您可以使用這個選項變更的 MongoDB 驅動程式,以指向 Azure Cosmos DB 執行個體,而不是指向預設本機執行個體,如我在這裡:

var connString=
  "mongodb://datapointsmongodbs:****.documents.azure.com:10255/?ssl=true";
ExpanseDb=new MongoClient(connString).GetDatabase("ExpanseDatabase");

我執行 ExpanseDatabase 船隻集合中插入新的出貨和新 DecommissionedShip 方法的重構的版本。重新整理 [總管] 中的資料庫之後, [總管] 中會顯示新建立的資料庫我的 Azure 帳戶、 集合和文件中的 Cosmos DB 資料庫中,如中所示**[圖 2**。

新建立的資料庫、 集合和 Cosmos DB 資料庫中的文件
[圖 2],新建立的資料庫、 集合和 Cosmos DB 資料庫中的文件

不是 Mongo DB 專家,但進一步了解多模型

此 API 的可用性不適合說服像我一樣具有數十年的經驗,使用 SQL 來切換至 [我的 Cosmos DB 資料庫中使用 MongoDB 的使用者。會有許多對我來說,了解。實際的目標是要啟用的無數的開發人員和小組已經使用 MongoDB 讓熟悉的體驗,同時獲得從 Azure Cosmos DB 所提供的眾多益處。我已進行自己的瀏覽到 Azure Cosmos DB API,若要進一步了解 Cosmos DB 多模型功能,以及對於已簽出新的資料庫的一些有趣的 mongodb。而且希望我的經驗會提供一些高階指引其他開發人員或用戶端在未來。


Julie Lerman是 Microsoft 區域經理,Microsoft MVP、 軟體小組教練和位於 Vermont 山區的顧問。您可以找到其呈現在資料存取和使用者群組和所做的心得世界各地的其他主題。她的部落格網址thedatafarm.com/blog是以及 Code First 和 DbContext 版本,所有從 O'Reilly Media"Programming Entity framework 」。在 Twitter 上關注她: @julielerman

非常感謝下列技術專家檢閱這篇文章:Nuri Halperin (加上 N 諮詢)


MSDN Magazine 論壇中的這篇文章的討論