MongoDB C# Driver 快速入門指南

如何在 Windows 上安裝 MongoDB
MongoDB C# Driver 管理快速入門指南

這是MongoDB driver的第一部分。在這一部分,你可以看到如何去執行一些數據庫的基本CRUD(C-創建,R-讀取,U-更新,D-刪除)操作。

連接

以下展示了三種連接到MongoDB遠程服務器和本地服務器的方式 :

// 連接到單實例MongoDB服務
// 這種連接方式不會自動檢測連接的節點是主節點還是復制集的成員節點
var client = new MongoClient();

// 或者使用string連接本地服務器,localhost=127.0.0.1,連接到單實例
var client = new MongoClient("mongodb://localhost:27017");

// 連接到復制集(多節點)
var client = new MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019");

客戶端實例現在可以擁有連接到連接字符串中指定的服務器或服務器的連接池。

MongoClient

MongoClient 實例實際上表示一個連接數據庫的連接池;

你僅僅只需要一個MongoClient 類實例,即使在多線程情況下;

標注:
實際上,你只需要為給定的集群創建一個MongoClient實例,并在應用程序中使用它。但是,如果連接字符串是相同的,那么創建多個MongoClient將仍然共享相同的連接池。

Get a Database

獲取一個數據庫實例,列舉數據庫的名稱可以通過client中的GetDatabase方法,在數據庫存在的情況下,該方式都是可行的。它將在首次被調用時創建。

var database = client.GetDatabase("foo");

現在,database變量保存了對數據庫“foo”的引用.

Get a Collection

獲取一個集合實例,列舉集合的名稱可以通過databaseGetCollection<TDocument>.在集合存在的情況下,它將在首次被調用時創建。

var collection = database.GetCollection<BsonDocument>("bar");

現在,collection變量保存了對數據庫“foo”下“bar”集合的引用.

標注:
泛型參數TDocument表示集合中存在的模式,使用一個BsonDocument來表示沒有預定的模式。

Insert a Document

一旦你擁有了collection實例,你就可以插入一個文檔到集合中。例如,考慮下面的JSON文檔,它是一個包含了一個字段信息的嵌入式文檔。

{
     "name": "MongoDB",
     "type": "database",
     "count": 1,
     "info": {
         x: 203,
         y: 102
     }
}

你可以使用.NET driver中的BsonDocument類創建這個文檔,方式如下:

var document = new BsonDocument
{
    { "name", "MongoDB" },
    { "type", "Database" },
    { "count", 1 },
    { "info", new BsonDocument
        {
            { "x", 203 },
            { "y", 102 }
        }
    }
};

把這個文檔插入到集合中,可以是使用InsertOne或者InsertOneAsync方法

collection.InsertOne(document);//同步
await collection.InsertOneAsycn(document);//異步
標注:
.NET driver 當前已全部支持異步操作。關于更多的async和await的信息,參見MSDN documentation
https://msdn.microsoft.com/en-us/library/hh191443.aspx
驅動中所有的API都已經同時支持同步和異步.

Insert Multiple Documents

插入多條數據到數據庫,可以使用InsertMany或者InsertManyAsync兩種方式.

// 生成 100 個counter從0~99遞增的文檔
var documents = Enumerable.Range(0, 100).Select(i => new BsonDocument("counter", i));

插入數據

collection.InsertManh(documnets);
await collection.InsertManyAsycn(documents);

Counting Documents

現在,我們插入了101個文檔到數據庫里面(100在循環中,首次插入1),我們可以核查這些數據,如果我們使用Count或者CountAsycn方法. 下面的代碼應該可以使得count的值為101.

var count = collection.Count(new BsonDocument());
or
var count = await collection.CountAsync(new BsonDocument());

標注:
空的BsonDocument參數是一個過濾器。在這里,指的是要計算所有的文檔.

Query the Collection

使用Find方法去集合中查詢. 該方法會返回一個IFindFluent<TDocument, TProjection> 實例,它提供一個接口鏈接find操作設置.

Find the First Document in a Collection

調用FirstOrDefault 或者FirstOrDefaultAsync 方法,可以獲取集合的第一個文檔.FirstOrDefault返回第一個文檔或者null. 當你只需要一個匹配的文檔或只對第一個文檔感興趣時,該方法非常有用.

下面的例子將會打印出再集合中查詢出來的第一個文檔:

var document = collection.Find(new BsonDocument()).FirstOrDefault();
Consloe.WriteLine(document.ToString());
var document = await collection.Find(new BsonDocument()).FirstOrDefaultAsync();
Console.WriteLine(document.ToString());

該例子將會打印出以下內容:

{ 
    "_id": ObjectId("5940f2b98198abd6a5eea7b1") },
    "name": "MongoDB", 
    "type": "database", 
    "count": 1,
    "info": { "x" : 203, "y" : 102 } 
}

元素 “id” 為 MongoDB 數據庫自動添加到文檔中,這是打印出來的內容與插入的內容不一致的原因。MongoDB數據庫內部保留所有以 “_”“$” 開頭的字段名稱.

Find All Documents in a Collection

使用ToList或者ToListAsycn方法可以檢索到集合中的所有文檔,當需要返回的文檔比較少量時,該方法非常有用.

var documents = collection.Find(new BsonDocument()).ToList();
var documents = await collection.Find(new BsonDocument()).ToListAsync();

如果返回的文檔數量比預期的大,可以使用通過迭代的方式進行處理。ForEachAsync將會為每個返回的文檔調用一個回調。

await collection.Find(new BsonDocument()).ForEachAsync(d => Console.WriteLined(d));

如果使用的是同步的API,則要使用C#中的ToEnumerable抽象方法去迭代每個文檔:

var cursor = collection.Find(new BsonDocument()).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}

上面的例子將會打印出相同的信息。更多的信息參見reference documention

Get a Single Document With a Filter

在一個集合中,我們可以創建一個篩選器傳遞給Find方法去獲取一個文檔的子集。例如,如果我們想查找“i”字段的值為71的文檔,我們可以使用如下的方式:

var filter = Builders<BsonDocument>.Filter.Eq("i", 71);
var document = collection.Find(filter).First();
Console.WriteLine(document);
var document = await collection.Find(filter).FirstAsync();
Console.WriteLine(document);

以上應該僅打印出一個文檔:

{ "_id" : ObjectId("5515836e58c7b4fbc756320b"), "i" : 71 }

標注:

使用 FilterSortProjection 以簡單和簡潔的方式創建一個查詢.

Get a Set of Documents With a Filter

我們也可以從集合中獲取一組文檔。例如,如果我們獲取所有符合 i > 50 條件的文檔,可以使用如下的方式:

var filter = Builders<BsonDocument>.Filter.Gt("i", 50);// Gt表示大于
var cursor = collection.Find(filter).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}
await collection.Find(filter).ForEachAsync(document => Console.WriteLine(document));

還可以限定一個范圍查詢,例如 50 < i <= 100;

var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Gt("i", 50) & filterBuilder.Lte("i", 100);//Lt表示小于,Lte表示小于等于
var cursor = collection.Find(filter).ToCursor();
foreach (var document in cursor.ToEnumerable())
{
    Console.WriteLine(document);   
}
await collection.Find(filter).ForEachAsync(document => Console.WriteLine(document));
Sorting Documents

我們可以通過調用 Sort 方法來創建一個排序匹配查詢。在現有的 filter 構造方法下,我們可以使用 Descending 建立一個降序構造器來排序我們的文檔:

var filter = Builders<BsonDocument>.Filter.Exists("i");
var sort = Builders<BsonDocument>.Sort.Descending("i");
var document = collection.Find(filter).Sort(sort).First();
var document = await collection.Find(filter).Sort(sort).FirstAsync();
Projecting Fields(映射字段)

很多時候,我們不需要文檔中包含的所有字段,Projection 構造器可以在一個查詢操作中構造映射字段。下面的例子中,我們排除了“_id”字段,并且輸出第一個匹配的文檔:

var projection = Builders<BsonDocument>.Projection.Exclude("_id");
var document = collection.Find(new BsonDocument()).Project(projection).First();
Console.WriteLine(document.ToString());
var document = await collection.Find(new BsonDocument()).Project(projection).FirstAsync();
Console.WriteLine(document.ToString());
Updating Documents

MongoDB 支持多種更新操作方式

更新最多一個文檔(如果沒有匹配篩選器,可能為零個文檔),使用UpdateOne或者UpdateOneAsync去指定篩選器并更新匹配的文檔。下面,我們更新篩選器為 i == 10 匹配的第一個文檔,并將該文檔 i 的值更新為110:

var filter = Builders<BsonDocument>.Filter.Eq("i", 10);
var update = Builders<BsonDocument>.Update.Set("i", 110);
collection.UpdateOne(filter, update);
await collection.UpdateOneAsync(filter, update);

更新篩選器匹配的所有文檔,使用UpdateMany或者UpdateManyAsync方法。下面例子,將把所有 i < 100 匹配的文檔中 i 的值增加 100。

var filter = Builders<BsonDocument>.Filter.Lt("i", 100);
var update = Builders<BsonDocument>.Update.Inc("i", 100);// Inc操作符表示:給i字段增加某個大小的值
var result = collection.UpdateOne(filter, update);

if (result.IsModifiedCountAvailable)
{
    Console.WriteLine(result.ModifiedCount);
}
var result = await collection.UpdateOneAsync(filter, update);

if (result.IsModifiedCountAvailable)
{
    Console.WriteLine(result.ModifiedCount);
}

更新方法返回的結果為UpdateResult,它提供關于該操作的信息,包括更新后修改的文檔的數量。

標注:

根據MongoDB數據庫的版本,某些特性可能無法使用。在這些情況下,我們已經嘗試了檢查是否有能力檢查它們的可用性。

Deleting Documents

刪除最多一個文檔(如果沒有匹配篩選器,可能為零個文檔),使用 DeleteOne 或者 DeleteOneAsync方法:

var filter = Builders<BsonDocument>.Filter.Eq("i", 110));
collection.DeleteOne(filter);
await collection.DeleteOneAsync(filter);

刪除篩選器匹配的所有文檔,使用DeleteMany 或者 DeleteManyAsync 方法。下面是刪除所有 i >= 100 匹配的文檔:

var filter = Builders<BsonDocument>.Filter.Gte("i", 100));// Gte表示大于等于
var result = collection.DeleteMany(filter);

Console.WriteLine(result.DeletedCount);
var result = await collection.DeleteManyAsync(filter);

Console.WriteLine(result.DeletedCount);

刪除方法返回的結果為DeleteResult ,它提供關于該操作的信息,包括刪除的文檔數量。

Bulk Writes (批量操作)

Bulk 操作有兩種類型:

  1. 有序Bulk操作

以有序的方式執行所有的操作,并且在首次遇到異常時拋出異常。

  1. 無序Bulk操作

執行所有的操作,并記錄操作過程中的全部異常。無序的批量操作不能保證執行的順序。

讓我們看一看下面的兩個關于有序和無序的操作例子:

var models = new WriteModel<BsonDocument>[] 
{
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 4)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 5)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 6)),
    new UpdateOneModel<BsonDocument>(
        new BsonDocument("_id", 1), 
        new BsonDocument("$set", new BsonDocument("x", 2))),
    new DeleteOneModel<BsonDocument>(new BsonDocument("_id", 3)),
    new ReplaceOneModel<BsonDocument>(
        new BsonDocument("_id", 3), 
        new BsonDocument("_id", 3).Add("x", 4))
};
// 1. 有序的批量操作 - 保證操作的順序
collection.BulkWrite(models);

// 2. 無序的批量操作 - 無法保證操作的順序
collection.BulkWrite(models, new BulkWriteOptions { IsOrdered = false });

異步

// 1. 有序的批量操作 - 保證操作的順序
await collection.BulkWriteAsync(models);

// 2. 無序的批量操作 - 無法保證操作的順序
await collection.BulkWriteAsync(models, new BulkWriteOptions { IsOrdered = false });

重要:

批量操作功能在MongoDB數據庫版本為2.6及之前的版本不被推薦使用,在性能上有較大的影響。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容