MongoDB C# Driver 快速入門指南

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

這是MongoDB driver的第一部分威鹿。在這一部分民效,你可以看到如何去執(zhí)行一些數(shù)據(jù)庫的基本CRUD(C-創(chuàng)建控乾,R-讀取,U-更新,D-刪除)操作。

連接

以下展示了三種連接到MongoDB遠(yuǎn)程服務(wù)器和本地服務(wù)器的方式 :

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

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

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

客戶端實例現(xiàn)在可以擁有連接到連接字符串中指定的服務(wù)器或服務(wù)器的連接池哄酝。

MongoClient

MongoClient 實例實際上表示一個連接數(shù)據(jù)庫的連接池;

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

標(biāo)注:
實際上,你只需要為給定的集群創(chuàng)建一個MongoClient實例直晨,并在應(yīng)用程序中使用它搀军。但是,如果連接字符串是相同的勇皇,那么創(chuàng)建多個MongoClient將仍然共享相同的連接池罩句。

Get a Database

獲取一個數(shù)據(jù)庫實例,列舉數(shù)據(jù)庫的名稱可以通過client中的GetDatabase方法儒士,在數(shù)據(jù)庫存在的情況下的止,該方式都是可行的。它將在首次被調(diào)用時創(chuàng)建着撩。

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

現(xiàn)在诅福,database變量保存了對數(shù)據(jù)庫“foo”的引用.

Get a Collection

獲取一個集合實例,列舉集合的名稱可以通過databaseGetCollection<TDocument>.在集合存在的情況下拖叙,它將在首次被調(diào)用時創(chuàng)建氓润。

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

現(xiàn)在,collection變量保存了對數(shù)據(jù)庫“foo”下“bar”集合的引用.

標(biāo)注:
泛型參數(shù)TDocument表示集合中存在的模式薯鳍,使用一個BsonDocument來表示沒有預(yù)定的模式咖气。

Insert a Document

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

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

你可以使用.NET driver中的BsonDocument類創(chuàng)建這個文檔伶唯,方式如下:

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);//異步
標(biāo)注:
.NET driver 當(dāng)前已全部支持異步操作惧盹。關(guān)于更多的async和await的信息乳幸,參見MSDN documentation
https://msdn.microsoft.com/en-us/library/hh191443.aspx
驅(qū)動中所有的API都已經(jīng)同時支持同步和異步.

Insert Multiple Documents

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

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

插入數(shù)據(jù)

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

Counting Documents

現(xiàn)在钧椰,我們插入了101個文檔到數(shù)據(jù)庫里面(100在循環(huán)中粹断,首次插入1),我們可以核查這些數(shù)據(jù),如果我們使用Count或者CountAsycn方法. 下面的代碼應(yīng)該可以使得count的值為101.

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

標(biāo)注:
空的BsonDocument參數(shù)是一個過濾器嫡霞。在這里瓶埋,指的是要計算所有的文檔.

Query the Collection

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

Find the First Document in a Collection

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

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

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

該例子將會打印出以下內(nèi)容:

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

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

Find All Documents in a Collection

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

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

如果返回的文檔數(shù)量比預(yù)期的大,可以使用通過迭代的方式進(jìn)行處理兵多。ForEachAsync將會為每個返回的文檔調(diào)用一個回調(diào)尖啡。

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

在一個集合中衅斩,我們可以創(chuàng)建一個篩選器傳遞給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);

以上應(yīng)該僅打印出一個文檔:

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

標(biāo)注:

使用 FilterSortProjection 以簡單和簡潔的方式創(chuàng)建一個查詢.

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

我們可以通過調(diào)用 Sort 方法來創(chuàng)建一個排序匹配查詢。在現(xiàn)有的 filter 構(gòu)造方法下极祸,我們可以使用 Descending 建立一個降序構(gòu)造器來排序我們的文檔:

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 構(gòu)造器可以在一個查詢操作中構(gòu)造映射字段遥金。下面的例子中浴捆,我們排除了“_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);
}

更新方法返回的結(jié)果為UpdateResult述吸,它提供關(guān)于該操作的信息,包括更新后修改的文檔的數(shù)量。

標(biāo)注:

根據(jù)MongoDB數(shù)據(jù)庫的版本蝌矛,某些特性可能無法使用道批。在這些情況下,我們已經(jīng)嘗試了檢查是否有能力檢查它們的可用性入撒。

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);

刪除方法返回的結(jié)果為DeleteResult ,它提供關(guān)于該操作的信息献雅,包括刪除的文檔數(shù)量碉考。

Bulk Writes (批量操作)

Bulk 操作有兩種類型:

  1. 有序Bulk操作

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

  1. 無序Bulk操作

執(zhí)行所有的操作侯谁,并記錄操作過程中的全部異常。無序的批量操作不能保證執(zhí)行的順序章钾。

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

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數(shù)據(jù)庫版本為2.6及之前的版本不被推薦使用墙贱,在性能上有較大的影響。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伍玖,一起剝皮案震驚了整個濱河市嫩痰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窍箍,老刑警劉巖串纺,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異椰棘,居然都是意外死亡纺棺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門邪狞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祷蝌,“玉大人,你說我怎么就攤上這事帆卓【揠” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵剑令,是天一觀的道長糊啡。 經(jīng)常有香客問我,道長吁津,這世上最難降的妖魔是什么棚蓄? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上梭依,老公的妹妹穿的比我還像新娘稍算。我一直安慰自己,他們只是感情好役拴,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布糊探。 她就那樣靜靜地躺著,像睡著了一般扎狱。 火紅的嫁衣襯著肌膚如雪侧到。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天淤击,我揣著相機(jī)與錄音匠抗,去河邊找鬼。 笑死污抬,一個胖子當(dāng)著我的面吹牛汞贸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播印机,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼矢腻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了射赛?” 一聲冷哼從身側(cè)響起多柑,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎楣责,沒想到半個月后竣灌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡秆麸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年初嘹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沮趣。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡屯烦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出房铭,到底是詐尸還是另有隱情驻龟,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布缸匪,位于F島的核電站翁狐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏豪嗽。R本人自食惡果不足惜谴蔑,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龟梦。 院中可真熱鬧隐锭,春花似錦、人聲如沸计贰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躁倒。三九已至荞怒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秧秉,已是汗流浹背褐桌。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留象迎,地道東北人荧嵌。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像砾淌,于是被迫代替她去往敵國和親啦撮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容