http://www.yuanjiaocheng.net/csharpmongo/16.html
介紹
在上一篇文章中,我們繼續探索MongoDb .NET驅動程式中的資料序列化。 我們檢視了各種屬性,如BsonIgnore,BsonRepresentation或BsonIgnoreIfNull。 資料序列化不是太複雜,隻要MongoDb中的文檔遵守一些模式,就像在我們的示範餐廳和郵政編碼集合。 一旦我們必須反序列化一組無序的文檔,那麼我們可能需要實作我們自己的序列化,事情變得更加複雜。 這是追蹤模式的另一個原因,即使MongoDb文檔是無模式的。
在這篇文章中,我們将介紹.NET驅動程式中的查詢技術。 我們将基于我們以前開始建構的示範.NET代碼。
Find方法
在撰寫本文時,T界面的IMongoCollection提供了以下Find方法:
- Find:一種擴充方法,使我們能夠以流暢的方式建構查詢,即我們可以連結與搜尋相關的各種其他方法
- FindSync:一種同步查找方法,它傳回一個遊标,并不像Find擴充方法那麼靈活
- FindAsync:一個異步的,即等待版本的FindSync
所有這些功能都接受基本上遵循兩種不同格式的過濾器,我們已經看到了兩個示例:FilterDefinition或傳回true的LINQ語句。 我發現Find擴充方法是上述最靈活的,因為它打開了以流暢的方式(如排序和限制)将其他與搜尋相關的查詢附加到其中的可能性。 是以,我會在這篇文章中堅持下去,但是要注意替代方案是很好的。
findOne和findall
回想一下,findOne()提供了一種快速了解Mongo shell中的文檔結構的方法。 我們如何在C#中寫同一個? 簡單:
1 2 | |
我們在LINQ語句中沒有任何過濾傳回true。 它相當于SQL中沒有where子句的SELECT * FROM語句。 然後,我們隻需附加熟悉的FirstOrDefault方法來擷取第一個文檔。
相反,如果我們要檢索所有沒有任何過濾器的文檔,那麼我們隻需應用ToList終端運算符:
|
當您輕觸IntelliSense提供的功能時,您會注意到FirstOrDefault和ToList方法都具有異步版本:FirstOrDefaultAsync和ToListAsync。 在MongoDb庫中,這是一個很常見的功能,它同時具有異步版本。
過濾基礎知識
如前所述,過濾可以使用特定于MongoDb庫的FilterDefinition對象或更一般的LINQ表達式來建構。 .NET程式員會意識到LINQ我相信我們從FilterDefinitionBuilder開始。 在我的經驗中,有一些複雜的過濾器定義隻能用這個特定的文法來表達,是以即使你是一個LINQ的狂熱者也是很好的。
過濾器定義使用通用Builders靜态類及其Filter屬性建構。 Builders類是建構一些不同定義對象的網關,FilterDefinitions隻是其中之一。 Filter屬性然後具有大量方法來幫助我們建構查詢。 我們以前已經看過一個例子:
|
如果您在Visual Studio中鍵入“Builders.Filter”,則IntelliSense将會提供或多或少對應于本系列中檢視的查詢操作符的多種功能。 例如。 Gt函數映射到$ gt運算符,Not to $ not等。在許多情況下,通過名稱來猜測函數的目的并不難,如Gt = GreaterThan。 Filter屬性具有一個名為Empty的特殊屬性,對應于在Mongo shell中的早期示例中看到的空的JSON過濾器{}。 它也是FilterDefinition等效于上面的Find示例中的“return true”LINQ語句。
Filter方法,如Eq和Gte,然後需要一個或多個參數。 Eq函數與其他類似的函數(如Gte和Lt)一樣,需要一個字段選擇器,形式為LINQ表達式,然後是過濾器值。 上面的例子選擇了一個名為“自治市鎮”的字段,我們要對值“布魯克林”過濾這個字段。
我們來看看一個使用FilterDefinition解決方案的邏輯AND運算符的例子:
3 4 5 6 | |
我們想在布魯克林找到第一間設有“熟食店”的餐廳。 “&”運算符是鍊條AND條件的簡短符号。 這是一個替代解決方案:
|
And函數接受帶有任意數量的過濾器定義的集合或參數數組,并将它們與AND結合在一起。 作為旁注,您可能會猜到有一個Or函數接受相同的過濾器定義參數,并将它們與邏輯OR連結在一起。 短的符号是單個管道字元“|”。
以下是一個例子:
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
這是LINQ風格的解決方案:
|
讓我們看看更複雜的一些:找到第一家餐廳,其等級陣列包括A,B和C級,即每個餐廳中至少有一個。 在這種情況下,我們需要深入對象圖。 Filter屬性具有一個All函數,它為數組字段建構$ all過濾器,但在這種情況下我們不能使用它。 如果等級數組隻是一個簡單的字元串數組,如“grade:[”A“,”B“]”,All方法将會有所幫助。 我們需要在這裡更深一層。
該解決方案以與AND相關聯的三個ElemMatch函數的形式。 ElemMatch函數接受集合字段,然後接收集合子屬性上的過濾器,如下所示:
|
這是一個與過濾器比對的餐廳:
|
該示例表明,有時我們需要在驅動程式中建立我們的查詢,以應用我們想要的,但最終我們可以找到相當于Mongo shell中寫入的過濾器。