{"id":81370,"date":"2018-10-24T20:02:08","date_gmt":"2018-10-24T20:02:08","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=81370"},"modified":"2026-03-06T13:14:21","modified_gmt":"2026-03-06T13:14:21","slug":"how-to-program-with-mongodb-using-the-net-driver","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/how-to-program-with-mongodb-using-the-net-driver\/","title":{"rendered":"MongoDB .NET Driver Guide: CRUD, LINQ &#038; Aggregation"},"content":{"rendered":"\n<p>The MongoDB .NET driver lets you connect to MongoDB from C# applications, map BSON documents to CLR types, and perform CRUD operations using both the native MongoDB API and LINQ syntax. If you\u2019re coming from SQL Server, the key mental shift is from tables and rows to collections and documents &#8211; but the .NET driver makes this transition easier by supporting familiar patterns like strongly-typed queries and LINQ expressions. This guide walks through environment setup, connection configuration, BSON type mapping, CRUD operations, aggregation pipelines, and authentication, with SQL-to-MongoDB comparisons throughout.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-getting-started\">Getting started<\/h2>\n\n\n\n<p>Many people that have a background in relational databases are confused with the terms NoSQL and <em>the document database<\/em>. What kind of documents are in the database and how to get data without the query language, without SQL? In my opinion, the term NoSQL does not mean that there is no schema, rather than the schema is not strictly enforced. And, of course, there is a query language as well.<\/p>\n\n\n\n<p>During the past few years, JSON has become extremely popular. Getting data from various forms (i.e., WEB and WIN forms) became extremely easy using JSON. Furthermore, saving such data as users entered them dictates the shape of the data. The shape of the data is determined by the application itself, unlike a relational database in which the data are independent of the application. In NoSQL databases, the data are saved in the JSON document. The table record in the relational world is equivalent to the JSON document in the NoSQL world.<\/p>\n\n\n\n<p>I think that it is easier to learn something new by comparing with something that you already know. This article will try to be a gentle introduction to the NoSQL world and will explain how to transform part of a well-known database, AdventureWorks2016, to NoSQL as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"631\" height=\"770\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-96.png\" alt=\"\" class=\"wp-image-81371\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>For this article, I had to choose between MongoDB and Cosmos DB. Both databases provide challenges and opportunities, but, in my opinion, MongoDB has an advantage. It provides more free options than Cosmos DB. Furthermore, MongoDB is a multiplatform database with an on-premise edition that is much richer than the Cosmos DB Emulator.<\/p>\n\n\n\n<p>Let\u2019s get started. The first step is to set up the environment. This means installing the MongoDB database, installing the NET driver, and importing some data.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-setting-up-the-environment\">Setting up the environment<\/h2>\n\n\n\n<p>At the time of this writing, October 2018, the current version of MongoDB in 4.0.2, and the current version of the .NET driver is 2.7. To install MongoDB, start with a Google search for \u2018Mongo DB download\u2019 or click on <a href=\"https:\/\/www.mongodb.com\/download-center#enterprise\">the link<\/a>. From the list of available platforms, choose Windows x64. Then fill in the form with your first and last name, e-mail address, and so on. After that, save the MSI installation file locally.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1027\" height=\"437\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-97.png\" alt=\"\" class=\"wp-image-81372\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The installation is straightforward. MongoDB will be installed as a Windows service by default. You have the option of choosing the service name, the service user, and startup folders for data and log files, as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"493\" height=\"387\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-98.png\" alt=\"\" class=\"wp-image-81373\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>If you choose the <strong>Custom<\/strong> installation option, you may specify an installation directory. The MongoDB installation will put the executables in <em>C:\\Program Files\\MongoDB\\Server\\4.0\\bin<\/em> folder by default. Be sure to add this path to your <em>PATH<\/em> environment variable to be able to run the MongoDB shell from any folder in the command prompt.<\/p>\n\n\n\n<p>Feel free to explore executables installed in the folder. The most important is <code>mongod<\/code> the windows service itself, <code>mongo<\/code> the shell and <code>mongoimport<\/code>, a utility that helps import various data in the database. You should also install the MongoDB GUI explorer called Compass from <a href=\"https:\/\/www.mongodb.com\/products\/compass\">the link<\/a>.<\/p>\n\n\n\n<p>The next step in setting the environment is to install the NET driver. To do that, start Visual Studio. I\u2019m using the VS 2017 Community Edition in this article.<\/p>\n\n\n\n<p>Create a new console project using C#, and name it as you wish. The purpose of creating a new project is to show you how to reference the MongoDB .NET driver. From the project context menu, choose <em>Manage NuGet Packages<\/em>. After <em>NuGet Package Manager<\/em> appears, enter <em>MongoDB driver<\/em> in the <em>Browse<\/em> tab as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"816\" height=\"261\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-99.png\" alt=\"\" class=\"wp-image-81374\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Choose and install <em>MongoDB.Driver<\/em>, and the three main components for programming MongoDB by using .NET are installed. All three are published together, as shown by version number, in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"477\" height=\"206\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-100.png\" alt=\"\" class=\"wp-image-81375\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>MongoDB.Bson<\/strong> handles various types and-file formats as well as the mapping between CLR types to BSon. BSon is MongoDB representation of JSON. I will write much more about BSon later.<\/p>\n\n\n\n<p><strong>MongoDB.Driver.Core<\/strong> handles connection pooling, communication between clients and database and so on. Usually, there is no need to work with this library directly.<\/p>\n\n\n\n<p><strong>MongoDB.Driver<\/strong> is where the main API is located.<\/p>\n\n\n\n<p>Once you download the three main libraries, you can start any new project and copy references from this first project. At this point, you can save and close this first project.<\/p>\n\n\n\n<p><strong>Read also:<\/strong> <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/working-with-json-in-sql-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSON handling in SQL Server<\/a><\/p>\n\n\n\n<p>In order to follow the article, please, download the article solution from the <a href=\"https:\/\/github.com\/Darko-Martinovic\/SimpleTalkMongoDb\">GitHub<\/a>. Open the solution by starting another instance of Visual Studio. In the solution notice the folder <em>Data<\/em> as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"254\" height=\"121\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-101.png\" alt=\"\" class=\"wp-image-81376\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The folder contains three JSON files that must be imported by using a MongoDB command line utility called <code>mongoimport<\/code>. Determine where on your local disk those three files are located. Start the command prompt from that location. In the command prompt window, execute the following three commands.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mongoimport&nbsp;--db&nbsp;simpleTalk&nbsp;--collection&nbsp;adventureWorks2016&nbsp;--file&nbsp;sales.json&nbsp;--jsonArray\n \nmongoimport&nbsp;--db&nbsp;simpleTalk&nbsp;--collection&nbsp;spetialOffer&nbsp;--file&nbsp;SpetailOffer.json&nbsp;--jsonArray\n \nmongoimport&nbsp;--db&nbsp;simpleTalk&nbsp;--collection&nbsp;products&nbsp;--file&nbsp;Product.json&nbsp;--jsonArray<\/pre>\n\n\n\n<p>By executing these commands, you will create a MongoDB database named <em>simpleTalk<\/em> (camel case naming) and three collections named: <em>adventureWorks2016<\/em>, <em>specialOffer<\/em>, and <em>product<\/em> as shown in the image below from Compass. When starting Compass, it tries to establish a connection on localhost port 27017. Just press <em>Connect<\/em> and, on the left side, select the database <em>simpleTalk<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1556\" height=\"395\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-102.png\" alt=\"\" class=\"wp-image-81377\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The collection in NoSQL is similar to the table in the SQL world and provides a namespace for the document. To prove that the import was successful, start the mongo shell from the command prompt. In the command prompt, type <code>mongo<\/code> to enter into the shell.<\/p>\n\n\n\n<p>Once you enter the shell, type <em>use simpleTalk<\/em> to switch in the context of the database. And then type <em>show collections<\/em> and you will be able to see all three imported collections.<\/p>\n\n\n\n<p>To conclude this first section, notice the Authentication folder in the article&#8217;s solution. Inside the folder, there is a JavaScript file named <em>AddUser.js<\/em>. If you are not in the mongo shell, start it again. In the context of the <em>simpleTalk<\/em> database, execute the code of <em>AddUser.js<\/em>, as shown in the snippet below, to create a user.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.createUser(\n{\n   user:&nbsp;\"usrSimpleTalk\",\n   pwd:&nbsp;\"pwdSimpleTalk\",\n   roles:&nbsp;[{&nbsp;role:&nbsp;\"readWrite\",&nbsp;db:&nbsp;\"simpleTalk\"&nbsp;}]\n}\n)<\/pre>\n\n\n\n<p>All examples in the article will execute in the context of this newly created user <em>usrSimpleTalk<\/em>. The user has been granted read and write permissions to the database.<\/p>\n\n\n\n<p>Now it\u2019s time to talk about how to connect to the MongoDB database, how CLR types are mapped to BSon types, and the root objects in the MongoDB .NET driver.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-connect-to-mongodb\">How to connect to MongoDB<\/h2>\n\n\n\n<p>The purpose of this section is to provide information on how to connect to the MongoDB database and to examine the most important objects of MongoDB API for .NET. Those objects are the MongoDB client, the Mongo database, and the Mongo collection. Open the article solution and make sure that the startup object is <em>Auth<\/em> as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"868\" height=\"568\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-103.png\" alt=\"\" class=\"wp-image-81378\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The class named <code>Auth<\/code> demonstrates how to connect to the MongoDB database. <code>MongoClient<\/code> is the root object that provides that connectivity.<\/p>\n\n\n\n<p>There are several various methods to connect to the database. The first way is to pass the database name, the username, and the password, as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;credential&nbsp;=MongoCredential.CreateCredential(databaseName:&nbsp;Dbase,&nbsp;username:&nbsp;UserName,&nbsp;password:&nbsp;Password);\n \nvar&nbsp;settings&nbsp;=&nbsp;new&nbsp;MongoClientSettings\n{\n    Credential&nbsp;=&nbsp;credential\n};\n \nvar&nbsp;mongoClient&nbsp;=&nbsp;new&nbsp;MongoClient(settings);<\/pre>\n\n\n\n<p>As you may have noticed by browsing the code, there is no need for opening, closing and disposing of connections. The client object is cheap, and the connection is automatically disposed of, unlike ADO.NET in which the connection is a very expensive resource. This approach is shown in the solution. In the solution, there is one configuration object located in the <em>Configuration<\/em> folder and named <em>SampleConfig<\/em>.<\/p>\n\n\n\n<p><strong>Read also:<\/strong> <a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-practical-guide-to-dapper\/\" target=\"_blank\" rel=\"noreferrer noopener\">Dapper for SQL Server data access in .NET<\/a><\/p>\n\n\n\n<p>The <code>MongoClient<\/code> has many overloads. The most common way to instantiate the client is to pass a connection string, as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/Using&nbsp;connectionString\nvar&nbsp;connectionString&nbsp;=&nbsp;$\"mongodb:\/\/{UserName}:{Passwrod}@localhost:27017\/{Dbase}\";\n \nmongoClient&nbsp;=&nbsp;new&nbsp;MongoClient(connectionString);<\/pre>\n\n\n\n<p>By default, MongoDB API uses port 27017 to communicate with the database, but there are many more options. That includes connecting to multiple servers, the replica sets and so on.<\/p>\n\n\n\n<p>At this point, I have to make a digression. One common thing that I would like to know is the number of currently opened connection. By using the mongo shell, it is possible to see that number but without further information.<\/p>\n\n\n\n<p>If you execute in the mongo shell command <code>db.serverStatus().connections<\/code>, you will see the response in the form of a document, as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"498\" height=\"59\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-104.png\" alt=\"\" class=\"wp-image-81379\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The only way to get more information is to use <code>netstat \u2013b<\/code> in the cmd window with elevated permissions and getting the result as displayed on the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"575\" height=\"73\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-105.png\" alt=\"\" class=\"wp-image-81380\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Let\u2019s get back to the main topic. Down in the object hierarchy is the database object. To get a reference to the database, usually, you execute the following snippet.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;db&nbsp;=&nbsp;mongoClient.GetDatabase($\"{Dbase}\");<\/pre>\n\n\n\n<p>The database is accessed in the context of the client. If you explore the exposed method in the client, you will notice that there are no options for creating a database. That is because the database is created automatically when it is needed and if it doesn\u2019t exist.<\/p>\n\n\n\n<p>In the context of the database, you can get a reference to the collection by executing snippet like shown below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;collection&nbsp;=&nbsp;db.GetCollection&lt;SalesHeader&gt;($\"{Collection}\");<\/pre>\n\n\n\n<p>or like this one<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> var&nbsp;collection&nbsp;=&nbsp;db.GetCollection&lt;BsonDocument&gt;($\"{Collection}\");<\/pre>\n\n\n\n<p>In the context of the database, you can create, drop, or rename a collection. There is a method to create a collection, but there is no need to use it because the collection will be created automatically if does not exist. The collection and the database object are both thread safe and could be instantiated once and used globally.<\/p>\n\n\n\n<p>As you noticed in the snippets above, the only difference in getting a reference to a collection object is by passing a type. This is the type needed in .NET to work with the collection. One is a <code>BsonDocument<\/code> that represents a dynamic schema in which you can use any document shape, and one is a so-called strongly typed schema named <code>SalesHeader<\/code>. As you will discover in the article, SalesHeader is the class that mimics the table in the <em>AdventureWorks2016<\/em> database named <em>Sales.SalesHeader<\/em>. The option that is strongly typed is the generally preferred way when working with MongoDB in .NET.<\/p>\n\n\n\n<p>The document object is found lower in the object hierarchy. The most general way to represent the document is to use the <code>BSonDocument <\/code>class. The BsonDocument is basically a dictionary of keys (strings) and <code>BsonValues<\/code>. <code>BsonValues<\/code> will be examined in the next section. To conclude this section, F5 to start the article&#8217;s solution. The result will display on the console screen. It represents the number of documents in the <code>adventureWorks2016<\/code> collection, and it is determined by calling the collections method <code>CountDocumentsAsync<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"976\" height=\"189\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-106.png\" alt=\"\" class=\"wp-image-81381\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-map-clr-types-to-bson-types\">How to map CLR types to BSON types<\/h2>\n\n\n\n<p>Change the startup object in order to follow this section. This time set <em>Attribute Decoration<\/em> located in the <em>Serialization<\/em> folder as the startup object. In the section, I will refer to a couple of simple classes which definitions can be found in the <em>Pocos<\/em> folder POCO is an acronym for \u2018plain old CLR object\u2019 and represents a class that is unencumbered by inheritance.<\/p>\n\n\n\n<p>The first example uses two objects. The first one is of type <code>TestSerializerWithOutAttributes<\/code>, the second one of type <code>TestSerializer<\/code>. Both classes define the same properties of type <code>bool, string, int, double<\/code> and <code>datetime<\/code>. The classes\u2019 definitions can be found in <em>TestSerializer.cs<\/em> located in the <em>Pocos<\/em> folder. The only difference between these two classes is that the second class has been decorated with attributes. In the example, I instantiate two objects and perform the basic serialization by using <code>ToJson<\/code>, as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1187\" height=\"573\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-107.png\" alt=\"\" class=\"wp-image-81382\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>By pressing F5, the result will be displayed as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"422\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-108.png\" alt=\"\" class=\"wp-image-81383\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>As you will notice, there are a couple of differences. One of them is that decimal type, by default, is displayed as a string. It must be decorated decimal type by attribute <code>[BsonRepresentation(BsonType.Decimal128)],<\/code> as is done in the definition of class <code>TestSerializer<\/code>.<\/p>\n\n\n\n<p>Then, if you noticed, the property <code>OnlyDate<\/code> is set by using the following snippet<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">OnlyDate = new DateTime (DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day),<\/pre>\n\n\n\n<p>Therefore, there is no time part. I am located in the UTC +1h time zone, and because it\u2019s currently daylight savings time, the default serializer reduces the date value by two hours. To avoid such behavior, I decorated, the property with the <code>attribute [BsonDateTimeOptions(DateOnly =true)].<\/code><\/p>\n\n\n\n<p>In the example, I am using some other attributes, which I\u2019ll describe. If you would like to change the element name or specify a different order, try decorating the property with <code>BsonElement<\/code> as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[BsonElement(\"description\", Order= 1)]\nPublic string Comment { get; set; }<\/pre>\n\n\n\n<p>As you\u2019ll see later, every <code>BsonDocument<\/code> that is part of a collection should have an element named <code>_id<\/code>. This is a kind of primary key in the NoSQL-Bson world. Also, by default, the collection is indexed by using this field. You are free to specify your own primary key by decorating a property or field in the class definition with the attribute <code>BsonId<\/code>, as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[BsonId]\npublic&nbsp;int&nbsp;SalesOrderId&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}<\/pre>\n\n\n\n<p>Finally, in order to specify that only a significant number of digits will be used when working with the double type, the following attribute is used:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;Double&nbsp;decorated&nbsp;with&nbsp;AllowTruncation&nbsp;\n[BsonRepresentation(BsonType.Double,&nbsp;AllowTruncation&nbsp;=&nbsp;true),&nbsp;BsonElement(\"myduble\")]\npublic&nbsp;double&nbsp;MongoValueTypeDouble&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}<\/pre>\n\n\n\n<p>You probably noticed that I use the word the default serializer, although in the code there is no call to any kind of serializer. This is because of the beautiful <code>.ToJson<\/code> extension. As you can see by using the Visual Studio <em>peek definition<\/em> or by pressing ALT + F12, <code>ToJson<\/code> is an extension of the object type defined in the <code>MongoDB.Bson<\/code> namespace. So, it should be safely used on any type.<\/p>\n\n\n\n<p>There is one thing about <code>ToJson<\/code> I have to write about at this spot. As you probably noticed, the extension optionally receives a parameter of type <code>JsonWriterSettings<\/code><strong>. <\/strong><\/p>\n\n\n\n<p>If you examine this class by using the Visual Studio <em>peek definition<\/em>, you will notice that the class has properties defined as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"644\" height=\"190\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-109.png\" alt=\"\" class=\"wp-image-81384\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>You can pay special attention to the property <code>outputMode<\/code>, as shown surrounded by red on the image above. This is an enumerator with two possible values. The default one is <code>JsonOutputMode.Shell<\/code> and the second one is <code>JsonOutputMode.Strict<\/code>. So, what is the difference? According to the <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/mongodb-extended-json\/\">MongoDB documentation<\/a> :<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Strict mode. Strict mode representations of BSON types conform to the <a href=\"http:\/\/www.json.org\/\">JSON RFC<\/a>. Any JSON parser can parse these strict mode representations as key\/value pairs; however, only the MongoDB internal JSON parser recognizes the type of information conveyed by the format.<\/li>\n\n\n\n<li>mongo Shell mode. The MongoDB internal JSON parser and the <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/program\/mongo\/#bin.mongo\">mongo<\/a> shell can parse this mode.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>My experience is that the <code>mongoimport<\/code> utility does not understand <code>shell<\/code> mode, so, I had to change the default serialization behavior to be mode <code>strict<\/code> in order to generate a JSON file that could be accepted by the mongoimport utility. You can find more about the differences between <code>strict<\/code> and <code>shell<\/code> mode <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/mongodb-extended-json\/\">here<\/a>.<\/p>\n\n\n\n<p>Besides decorating classes with attributes, there is an option to use so-called <code>ClassMap<\/code>. For example, if you want to keep serialization details out of their domain classes and do not want to play with attributes, you will use the <code>ClassMap<\/code> approach instead. This is not the only scenario in which you might use <code>ClassMap<\/code>. You can combine attribute decoration with <code>ClassMap<\/code> as well.<\/p>\n\n\n\n<p>To practice working with <code>ClassMap<\/code>, switch the startup object in the article\u2019s solution to <code>ClassMap<\/code>. In this example, I\u2019m using the same type as before, an object of type <code>TestSerializerWithOutAttributes<\/code>, to produce the same output as in the previous example.<\/p>\n\n\n\n<p>The class should be registered only once like is shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">if&nbsp;(!BsonClassMap.IsClassMapRegistered(typeof(TestSerializerWithOutAttributes)))\n{\n   BsonClassMap.RegisterClassMap&lt;TestSerializerWithOutAttributes&gt;(cm&nbsp;=&gt;<\/pre>\n\n\n\n<p>An exception will be thrown if you try to register the same class more than once. Internally, <code>BsonClassMap<\/code> holds information about registered types in a dictionary like shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">private static readonly Dictionary&lt;Type, BsonClassMap&gt; __classMaps = new Dictionary&lt;Type, BsonClassMap&gt;();<\/pre>\n\n\n\n<p>So, registering a class twice means adding a key to the dictionary that exists, which is, on the other hand, an exception. Usually, you call <code>RegisterClassMap<\/code> from some code path that is known to execute only once (the <code>Main<\/code> method, the <em>Application_Start<\/em> event handler, etc.).<\/p>\n\n\n\n<p>The most common way when working with <code>ClassMap<\/code> is to use so-called <code>AutoMap<\/code> and after that perform some add-on coding as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">if&nbsp;(!BsonClassMap.IsClassMapRegistered(typeof(TestSerializerWithOutAttributes)))\n{\n       BsonClassMap.RegisterClassMap&lt;TestSerializerWithOutAttributes&gt;(cm =&gt;\n       {\n           \/\/only read and write properties are mapped\n           cm.AutoMap();\n            \/\/BsonId attribute\n           cm.MapIdProperty(c =&gt; c.SalesOrderId);\n            \/\/Setting ElementName and Order\n           cm.GetMemberMap(c =&gt; c.Comment).SetElementName(\"description\").SetOrder(1);\n       }\n}<\/pre>\n\n\n\n<p>In the article\u2019s solution, there is an example showing how to use <code>AutoMap <\/code>named <code>ClassMapAutoMap<\/code>, located in <em>Serialization<\/em> folder. However, I will not use this option in the article. For example, to specify that the decimal type should be rendered (<strong>NOTE<\/strong>: I use term rendered and serialized interchangeably) as a decimal rather than strings, following code is used. Notice that there is a predefined serializer for a <code>decimal <\/code>type.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;Setting&nbsp;the&nbsp;default&nbsp;decimal&nbsp;serializer\ncm.MapProperty(c&nbsp;=&gt;&nbsp;c.Salary).SetSerializer(new&nbsp;DecimalSerializer(BsonType.Decimal128));<\/pre>\n\n\n\n<p>In order to specify the element name and change the order that the element is rendered, the following snippet is used:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/Setting&nbsp;ElementName&nbsp;and&nbsp;Order\ncm.MapProperty(c&nbsp;=&gt;&nbsp;c.Comment).SetElementName(\"description\").SetOrder(1);<\/pre>\n\n\n\n<p>To serialize the <code>DateTime<\/code> type with only the date part, or to use Local Time, the following snippet is used. Notice that there is predefined serializer for the <code>datetime<\/code> type.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cm.MapProperty(c&nbsp;=&gt;&nbsp;c.OnlyDate).SetSerializer(new&nbsp;DateTimeSerializer(dateOnly:&nbsp;true));\ncm.MapProperty(c&nbsp;=&gt;&nbsp;c.LocalTime).SetSerializer(new&nbsp;DateTimeSerializer(DateTimeKind.Local));<\/pre>\n\n\n\n<p>Similarly, to specify that <code>SalesOrderId<\/code> should be treated as a <code>BsonId<\/code>, the following snippet is used<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;BsonId&nbsp;attribute\ncm.MapIdProperty(c&nbsp;=&gt;&nbsp;c.SalesOrderId);<\/pre>\n\n\n\n<p>Finally, to specify only a significant part of the digits to be serialized when working with the <code>double<\/code> type, the following code snippet is used<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;we&nbsp;have&nbsp;to&nbsp;set&nbsp;an&nbsp;object&nbsp;of&nbsp;type&nbsp;RepresentationConverter&nbsp;and&nbsp;pass&nbsp;allowTruncation&nbsp;'true'\nvar&nbsp;rp&nbsp;=&nbsp;new&nbsp;RepresentationConverter(allowOverflow:&nbsp;false,&nbsp;allowTruncation:&nbsp;true);\ncm.MapProperty(c&nbsp;=&gt;&nbsp;c.MongoValueTypeDouble).SetElementName(\"mydouble\")\n           .SetSerializer(new&nbsp;DoubleSerializer(BsonType.Double,&nbsp;converter:&nbsp;rp));<\/pre>\n\n\n\n<p>Also, by pressing F5, you should get the same result as in the previous example.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"234\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-110.png\" alt=\"\" class=\"wp-image-81385\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>That is not the end of the possibilities. There is an option to use the so-called <code>Convention Pack<\/code>. In short, to be able to follow the section from this point, change the startup object to be <em>TestConventionPack<\/em>.<\/p>\n\n\n\n<p>When working with <code>ClassMap<\/code> and \u2018automapping,\u2019 many decisions should be made. What property should be <code>BsonId<\/code>, how should the <code>decima<\/code>l type be serialized, what will be the element name, and so on?<\/p>\n\n\n\n<p>Answers to these questions are represented by a set of conventions. For each convention, there is a default convention that is the most likely one you will be using, but you can override individual conventions and\/or write your own convention.<\/p>\n\n\n\n<p>If you want to use your own conventions that differ from the defaults, simply create an instance of <code>ConventionPack<\/code><strong>, <\/strong>add in the conventions you want to use, and then register that pack (in other words, tell the default serializer when your special conventions should be used).<\/p>\n\n\n\n<p>For example, to instantiate an object of the type of <code>ConventionPack<\/code><strong>,<\/strong> you might use the following snippet:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;conventions&nbsp;=&nbsp;new&nbsp;ConventionPack\n{\n    new&nbsp;CamelCaseElementNameConvention(),\n    new&nbsp;DecimalRepresentationConvention(BsonType.String),\n    new&nbsp;DateOnlyRepresentation(BsonType.DateTime),\n    new&nbsp;LocalDateRepresentation(BsonType.DateTime)\n};<\/pre>\n\n\n\n<p>The first convention, <code>CamelCaseElementNameConvention<\/code><strong>,<\/strong> will tell default serializer to put all elements name in CamelCase. This is a predefined convention. All other conventions are defined in the example and represent the custom conventions. <code>DecimalRepresentationConvention<\/code> will tell the default serializer to serialize all <code>decimal <\/code>properties as a <code>decimal<\/code>, rather than a <code>string<\/code>, which is the default option. Similar to this is the <code>DateOnlyRepresentation<\/code> and <code>LocalDateReporesentation<\/code>. When working with <code>ClassMap<\/code>, you should connect your class with convention pack. This is usually accomplished like is shown in the code snippet:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ConventionRegistry.Register(\"Test\",&nbsp;conventions,\ntype&nbsp;=&gt;&nbsp;type.FullName&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;type.FullName.Contains(\"TestSerializerWithOutAttributes\"));<\/pre>\n\n\n\n<p>In the <em>Serialization<\/em> folder, there is a class named <code>TestTypes<\/code> as well. Please, change the startup object to be <em>TestTypes<\/em>. This example shows how complex types are transformed into JSON(BSON). This includes .NET native types like generic collections, as well as classes that inherit from other classes. When a class inherits from other class, a special field <code>_t<\/code>, that represents the type, is rendered as shown in the image below, surrounded with red.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"793\" height=\"395\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-111.png\" alt=\"\" class=\"wp-image-81386\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>As a take away from this section, it\u2019s possible to decorate the class with attributes, work with <code>ClassMap<\/code>, and, finally, work with <code>ConventionPack<\/code>.<\/p>\n\n\n\n<p>API is very easy to use and very hard to misuse when working with serialization. Now it is time to talk about collections. How are they designed? The next section is about schema design.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-schema-design\">Schema design<\/h2>\n\n\n\n<p>One of the documents in the <em>adventureWorks2016<\/em> collection looks as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"631\" height=\"767\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-112.png\" alt=\"\" class=\"wp-image-81387\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>As you\u2019ll notice, a detail array that represents details of an order is embedded in the document. In the SQL world, details of an order are put in a separate table known as <em>Sales.SalesDetail<\/em>. You could do the same thing in MongoDB, e.g., put details in a separate collection, but as you may recall from the introduction, in the NoSQL world, the shape of the data is determined by the application itself. There\u2019s a good chance that when you are working with the sales data, you probably need sales details. The decision about what to put in the document is pretty much determined by how the data is used by the application. The data that is used together as sales documents is a good candidate to be pre-joined or embedded.<\/p>\n\n\n\n<p>One of the limitations of this approach is the size of the document. It should be a maximum of 16 MB.<\/p>\n\n\n\n<p>Another approach is to split data between multiple collections which is also used in the article solution. For example, details about products and special offers are separated into another collection. One of the limitations of this approach is that there is no constraint in MongoDB, so there are no foreign key constraints as well. The database does not guarantee consistency of the data. Is it up to you as a programmer to take care that your data has no orphans.<\/p>\n\n\n\n<p>Data from multiple collections could be joined by applying the <code>lookup<\/code> operator, as I\u2019ll show in the section that talks about aggregations. But, a collection is a separate file on disk, so seeking on multiple collections means seeking from multiple files, and that is, as you are probably guessing, slow. Generally speaking, embedded data is the preferable approach.<\/p>\n\n\n\n<p>The underlying CLR class to work with the <em>adventureWorks2016<\/em> collection is <em>SalesHeader<\/em>. Its definition is located in the <code>Pocos<\/code> solution folder.<\/p>\n\n\n\n<p>In the class definition, the detail is represented as shown in the following snippet.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public&nbsp;List&lt;SalesDetail&gt;&nbsp;Details&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}<\/pre>\n\n\n\n<p>It is a generic List of <code>SalesDetail<\/code>. The <code>SalesDetail <\/code>class mimics the <em>Sales.SalesDetail<\/em> table. The CLR class to work with the <code>product<\/code> collection is <code>Product<\/code> and, to work with the <em>spetialOffer<\/em> collection, a class <code>SpetialOffer<\/code> is designed. The source code that shows you how these collections are generated is located in the <em>Loaders<\/em> folder.<\/p>\n\n\n\n<p>The image below displays the content of the <em>spetailOffer<\/em> collection.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"994\" height=\"696\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-113.png\" alt=\"\" class=\"wp-image-81388\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The <em>spetialOffer<\/em> collection will be used in the next section, which talks about C(reate), R(ead), U(pdate) &amp; D(elete) operations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-crud-operations\">CRUD Operations<\/h2>\n\n\n\n<p>To follow this section, change the startup object of the article\u2019s solution to <em>CrudDemo<\/em><strong>.<\/strong> This example demonstrates how to add, modify and, finally, delete a couple of documents in the <em>spetialOffer<\/em> collection.<\/p>\n\n\n\n<p>As you may recall from the previous section, the <em>spetailOffer<\/em> collection has IDs from 1 to 16. If you try to add an ID that already exists, a run-time exception will occur. For example, you can define an object of type <code>SpetialOffer<\/code>, as shown in the following snippet:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var  so = new SpetialOffer\n{\n    SpecialOfferId = 1,\n    Description = \"Test inserting one\",\n    Type = \"New Product\",\n    Category = \"Reseller\"\n};\nawait collection.InsertOneAsync(so);\n\/\/A write operation resulted in an error.E11000 duplicate key error collection: simpleTalk.spetialOffer index: _id_ dup key: { : 1 }<\/pre>\n\n\n\n<p>Running this will return an exception with the message shown in the snippet. Finally, try inserting a document that has an ID of 20.<\/p>\n\n\n\n<p>In order to get the document, the <code>Find <\/code>extension of <code>IMongoCollection<\/code> is used as shown in the following snippet.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;result&nbsp;=&nbsp;await&nbsp;collection.Find(x&nbsp;=&gt;&nbsp;x.SpecialOfferId&nbsp;==&nbsp;IdToAdd).ToListAsync();<\/pre>\n\n\n\n<p>To insert many documents into a collection, you have to pass an enumerable collection of the document to the <code>InsertMany<\/code> method. <code>InsertMany<\/code> is an extension of <code>IMongoCollection<\/code>. To insert in the collection documents with ID 30 and 31, you could execute the code snippet shown below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var so = new[]\n         {\n         new SpetialOffer\n             {\n             SpecialOfferId = IdToAddMany,\n             Description = \"Test inserting many 1\",\n             Type = \"New Product\",\n             Category = \"Reseller\"\n            },\n           new SpetialOffer\n           {\n             SpecialOfferId = IdToAddMany2,\n             Description = \"Test inserting many 2\",\n             Type = \"New Product\",\n             Category = \"Reseller\"\n           }\n        };\nvar imo = new InsertManyOptions\n        {\n          IsOrdered = false\n        };\nawait collSpetialOffer.InsertManyAsync(so,imo);<\/pre>\n\n\n\n<p>One interesting thing to notice is the second parameter of <code>InsertManyAsync<\/code>. It is an object of type <code>InsertManyOptions<\/code>. Particularly, its property <code>IsOrdered <\/code>is interesting. When set to false, the insertion process will continue on error.<\/p>\n\n\n\n<p>There are two kinds of updates. There is a replace extension which replaces the entire document, and there is an update extension that updates just the particular field or fields in the document. When replacing a document, first you have to specify a filter function to find the document(s) to be replaced. It is not possible to change ID during replacement. If you try to do something like that an exception will be thrown. If you specify a condition that does not match any documents, the default behavior is to do nothing.<\/p>\n\n\n\n<p>Usually, if you want to replace one document, a snippet like following is used:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;It&nbsp;is&nbsp;not&nbsp;possible&nbsp;to&nbsp;change&nbsp;ID&nbsp;!!!\n\/\/&nbsp;if&nbsp;we&nbsp;specify&nbsp;the&nbsp;condition&nbsp;that&nbsp;has&nbsp;no&nbsp;matching&nbsp;document&nbsp;default&nbsp;behavior&nbsp;is&nbsp;to&nbsp;do&nbsp;nothing!\nvar&nbsp;so&nbsp;=&nbsp;new&nbsp;SpetialOffer\n{\n   SpecialOfferId&nbsp;=&nbsp;IdToAdd,\n   Description&nbsp;=&nbsp;\"NEW&nbsp;DESCRIPTION\",\n   Type&nbsp;=&nbsp;\"NEW&nbsp;TYPE\",\n   Category&nbsp;=&nbsp;\"NEW&nbsp;Reseller\"\n};\nawait&nbsp;collection.ReplaceOneAsync(x&nbsp;=&gt;&nbsp;x.SpecialOfferId&nbsp;==&nbsp;IdToAdd,&nbsp;so);<\/pre>\n\n\n\n<p><code>ReplaceOneAsync <\/code>is an extension of the <code>IMongoCollection<\/code> and represents a high order function which takes as a parameter another function \u2013 lambda expression. One of the parameters that is not provided in the above snippet is <code>UpdateOptions<\/code>. In my opinion, a better name should be ReplaceOptions because it\u2019s in the context of Replacing. Particularly, in that class, a property <code>IsUpsert <\/code>is interesting. When specified to be true, an insert is made if the filter condition did not match any document.<\/p>\n\n\n\n<p>When updating the document, usually you will execute a snippet like that shown below<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">private&nbsp;const&nbsp;int&nbsp;IdToAdd&nbsp;=&nbsp;20;\n-----\nvar&nbsp;ud&nbsp;=&nbsp;Builders&lt;SpetialOffer&gt;.Update.Set(\"Description\",&nbsp;\"Descripton&nbsp;from&nbsp;update\");\nawait&nbsp;collection.UpdateOneAsync(x&nbsp;=&gt;&nbsp;x.SpecialOfferId&nbsp;==&nbsp;IdToAdd,&nbsp;ud);<\/pre>\n\n\n\n<p>In the above snippet, I\u2019m using an example with <code>Builders<\/code>. <code>Builders<\/code> are classes that make it easier to use the CRUD API. <code>Builders<\/code> help define an update condition. This time, only part of a document has been changed. Similar to another CRUD extension of <code>IMongoCollection<\/code> is the <code>Delete<\/code> extension. For example, the following snippet will delete the document with ID 20.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;result&nbsp;=&nbsp;await&nbsp;collSpetialOffer.DeleteOneAsync(x&nbsp;=&gt;&nbsp;x.SpecialOfferId&nbsp;==&nbsp;IdToAdd);\nConsole.WriteLine($\"Is&nbsp;deleted&nbsp;completed&nbsp;:&nbsp;{result.IsAcknowledged}\");<\/pre>\n\n\n\n<p>There are more extensions like <code>FindOneAndUpdate, FindOneAndReplace<\/code>, <code>FindOneAndDelete<\/code><strong>,<\/strong> and so on.<\/p>\n\n\n\n<p>There is no transaction in MongoDB, but there is the so-called atomic operation. Any write operation on the particular document is guaranteed to be atomic \u2013 not breakable. Starting with MongoDB 4.0 there is a transaction, but they are limited only for replica sets. (<strong>NOTE<\/strong>: A replica set in MongoDB is a group of <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/program\/mongod\/#bin.mongod\">mongod<\/a> processes that maintain the same data set ).<\/p>\n\n\n\n<p>In the article\u2019s solution, there is an example that uses a transaction, named <code>InsertOneWithTransaction<\/code>. It is commented, but in short, in order to use the transaction, a session object should be created in the context of the MongoDB client. Then the session object starts the transaction, and the session object is passed to CRUD methods (extensions) as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/&nbsp;return&nbsp;IClientSessionHandle&nbsp;object\nvar&nbsp;session&nbsp;=&nbsp;SampleConfig.Client.StartSession();\n\/\/&nbsp;start&nbsp;transaction\nsession.StartTransaction(new&nbsp;TransactionOptions(readConcern:&nbsp;ReadConcern.Snapshot,\nwriteConcern:&nbsp;WriteConcern.WMajority));\ntry\n{\n\/\/&nbsp;Note&nbsp;we&nbsp;have&nbsp;to&nbsp;pass&nbsp;session&nbsp;object\nawait&nbsp;collection.InsertOneAsync(session,&nbsp;so);\nawait&nbsp;collection.InsertOneAsync(session,&nbsp;so);\n\/\/&nbsp;the&nbsp;transaction&nbsp;is&nbsp;commited\nsession.CommitTransaction();\n}\ncatch&nbsp;(Exception&nbsp;ex)\n{\n     \/\/&nbsp;the&nbsp;transaction&nbsp;is&nbsp;aborted\n      session.AbortTransaction();\n}<\/pre>\n\n\n\n<p>All examples in this section use the async stack and TPL library (task parallel library). There is also a sync stack as well, but the first one should be considered as a modern way of programming and was introduced with driver version 2.X.<\/p>\n\n\n\n<p>In this section, I just briefly mentioned how to read and filter data. The next section will talk more about how to filter data.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-filtering\">Filtering<\/h2>\n\n\n\n<p>To follow this section, set up <em>FindWithCursor<\/em> as a startup object for the article solution. In this example, I query documents where<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>TerritoryId equal to 1,<\/li>\n\n\n\n<li>SalesPersonId equal to 283,<\/li>\n\n\n\n<li>Total Due greater than 90000<\/li>\n\n\n\n<li>and limiting the number of documents to be returned to 5,<\/li>\n\n\n\n<li>Sorting the result ascending by Due Date.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>The task is accomplished by utilizing <code>Find<\/code>, an extension of <code>IMongoCollection<\/code>. <code>Find<\/code> is defined as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"912\" height=\"133\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-114.png\" alt=\"\" class=\"wp-image-81389\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>It returns an <code>IFindFluent<\/code>, which is a context type for method chaining in searching documents. Other methods like <code>Sort, Limit, Project<\/code> in context of <code>IMongoCollection <\/code>return <code>IFindFluent<\/code>.<\/p>\n\n\n\n<p><code>Find<\/code> takes two parameters, a lambda expression and an object of type <code>FindOptions<\/code>. Besides other properties, <code>FindOptions<\/code> defines the batch size. By using <code>Find <\/code>you could get a result in chunks. If you limit the number of the document to 5, a total of 3 batches is returned to the client. The complete code is shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"53\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-115.png\" alt=\"\" class=\"wp-image-81390\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"954\" height=\"392\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-116.png\" alt=\"\" class=\"wp-image-81391\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Getting the next batch is accomplished by invoking <code>cursor.Result.MoveNextAsync<\/code>. Inside that batch, you can iterate through the documents by processing <code>cursor.Result.Current<\/code>. The benefit of that approach is that if you get a large number of documents as a result, you can process them in batches, which will use less memory.<\/p>\n\n\n\n<p>There is an option to get all results by invoking <code>ToListAsync()<\/code>. In that case, all returned documents live in memory, and there is an option to process the cursor using <code>ForEachAsync<\/code> as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"118\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-117.png\" alt=\"\" class=\"wp-image-81392\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Invoking <code>cursor.ToString()<\/code>will return a MongoDB shell query. I did not find a proper way to get the query plan in the code. It was possible before the 2.7 release of the .NET driver. In the article\u2019s solution, there is an example of how to get the query plan from the code. The example is named <em>Explain<\/em> and is located in the <em>Filtering<\/em> folder.<\/p>\n\n\n\n<p>To get the execution plan, you could save the query text and execute in the context of the Mongo shell. I saved the query in a file <em>QueryUsingCursor.js<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"956\" height=\"49\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-118.png\" alt=\"\" class=\"wp-image-81393\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>So, if you append <code>explain()<\/code> before <code>find<\/code><strong>, <\/strong>you will be able to see the execution plan.<\/p>\n\n\n\n<p><code>Explain<\/code> receives a parameter that describes what the type of output should be. The parameter specifies the verbosity mode for the explain output. The mode affects the behavior of <code>explain()<\/code> and determines the amount of information to return. The possible modes are <code>queryPlanner<\/code>, <code>executionStats<\/code>, and <code>allPlansExecution<\/code>.<\/p>\n\n\n\n<p>The example uses <code>executionStats<\/code>. The plan is shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"479\" height=\"370\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-119.png\" alt=\"\" class=\"wp-image-81394\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>As you can see, to return five documents, you have to process all the documents in the collection. That is the part when the index comes to play. To create an index, you should execute a command shown in the image below, in the context of the <em>simpleTalk<\/em> database.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"312\" height=\"54\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-120.png\" alt=\"\" class=\"wp-image-81395\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The rule in index creation requires a field that participates in filtering first and then fields that are included in sorting.<\/p>\n\n\n\n<p>An index could be created in the foreground which is the default. What does it mean<em>? <\/em>MongoDB documentation states<em>: \u2018By default, creating an index on a populated collection blocks all other operations on a database. When building an index on a populated collection, the database that holds the collection is unavailable for reading or write operations until the index build completes. Any operation that requires a read or writes lock on all databases will wait for the foreground index build to complete&#8217;. <\/em>This does not sound good.<\/p>\n\n\n\n<p>For potentially long-running index building operations on standalone deployments, the background option should be used. In that case, the MongoDB database remains available during the index building operation.<\/p>\n\n\n\n<p>To create an index in the background, the following snippet should be used. There is no need to create the index again. This index is small, and it&#8217;s creation takes a few seconds.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"648\" height=\"55\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-121.png\" alt=\"\" class=\"wp-image-81396\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In MongoDB, there is no need to rebuild indexes. The database itself takes care of everything. Great!<\/p>\n\n\n\n<p>Let\u2019s get back to the main topic about the query plan. After the index is created, examine the execution plan again.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"382\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-122.png\" alt=\"\" class=\"wp-image-81397\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>As you can see, highlighted with yellow, the execution plan looks much better now. Only five documents are examined.<\/p>\n\n\n\n<p>Another example located in the <em>Filter<\/em> folder named <em>FilterHeader<\/em> uses the MongoDB aggregation framework to query the document, which is the next section. To explore this example, change the startup object to be <em>FilterHeader<\/em>, and you will receive the output as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"469\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-123.png\" alt=\"\" class=\"wp-image-81398\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-aggregation\">Aggregation<\/h2>\n\n\n\n<p>Aggregation operations process some input data, in the case of MongoDB, documents and return computed results. Aggregation operations group values from multiple documents together and can perform a variety of operations on the grouped data to return a single result. MongoDB provides three ways to perform aggregation:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>the aggregation pipeline,<\/li>\n\n\n\n<li>the <a href=\"https:\/\/docs.mongodb.com\/manual\/aggregation\/#single-purpose-agg-operations\">single purpose aggregation methods<\/a>,<\/li>\n\n\n\n<li>the map-reduce function.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>I will write mostly about the first by introducing a common problem in the SQL world that is called <em>TOP n per group<\/em>. The single purpose aggregation methods are briefly mentioned in the first example that connects to MongoDB when <code>Count<\/code> was introduced. Map-reduce was the only way to aggregate in prior versions of MongoDB.<\/p>\n\n\n\n<p>In MongoDB, there is a difference when querying embedded documents such as sales details, or the main document. In the first case, the <code>unwind<\/code> operator must be introduced. So, I decided to include the same problem twice.<\/p>\n\n\n\n<p>The first example finds the top N (one) customer per territory that has the greatest Total Due and then limits the result to those territories and customers where the sum of Total Due is greater than the Limit (a defined number). The result should be sorted on Sum of Total Due descending order. The second example does something similar with special offer and products.<\/p>\n\n\n\n<p><strong>Read also:<\/strong> <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/sql-server-group-by-basics\/\" target=\"_blank\" rel=\"noreferrer noopener\">SQL Server aggregation and GROUP BY<\/a><\/p>\n\n\n\n<p>There are a couple of ways to accomplish this task in SQL. In the article\u2019s solution, I include two T-SQL scripts, located in TSQL folder. One for querying the header table named <em>QueryingHeader.sql,<\/em> and one for querying the detail table named <em>QueryingDetail.sql<\/em><strong>.<\/strong><\/p>\n\n\n\n<p>I provided three possible ways to solve the problem in T-SQL, by using T-SQL window functions and the APPLY operator.<\/p>\n\n\n\n<p>Both results for querying the header and the detail table, are displayed in the image below. In the first case, the limit is 950.000, and in the second case, the limit is 200.000.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"288\" height=\"122\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-124.png\" alt=\"\" class=\"wp-image-81399\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"292\" height=\"126\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-125.png\" alt=\"\" class=\"wp-image-81400\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>To see how is the problem solved in MongoDB, switch the startup object of the article\u2019s solution to be <em>AggregationSales<\/em>.<\/p>\n\n\n\n<p>In the class, there are three ways how to accomplish the same task.<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Using IAggregateFluent<\/li>\n\n\n\n<li>Using LINQ<\/li>\n\n\n\n<li>Parsing BsonDocument ( the MongoDB\u2019s shell-like syntax )<\/li>\n<\/ul>\n<\/div>\n\n\n<p>The first way is shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var result = collection.Aggregate(aggregationOptions)\n           .Group(x =&gt; new { x.TerritoryId, x.CustomerId },\ng =&gt;new { TerritoryIdCustomerId = g.Key, TotalDue = g.Sum(x =&gt; x.TotalDue) })\n         .SortBy(x =&gt; x.TotalDue)\n         .Group(x =&gt; x.TerritoryIdCustomerId.TerritoryId, g =&gt; new\n         {\n             TerritoryId = g.Key,\n             MaxCustomer = g.Last().TerritoryIdCustomerId.CustomerId,\n             MaxTotal = g.Last().TotalDue\n         })\n        .Match(x =&gt; x.MaxTotal &gt; Limit)\n        .Project(x =&gt; new\n        {\n           x.TerritoryId,\n           MaxCust = new { Id = x.MaxCustomer, Total = x.MaxTotal },\n        })\n        .SortByDescending(x =&gt; x.MaxCust.Total);\nvar&nbsp;queryToExplain =query.ToString();\n \nvar result = await query.ToListAsync();<\/pre>\n\n\n\n<p>First, you have to notice that everything in the snippet above is strongly typed!<\/p>\n\n\n\n<p>Then, you should notice that <code>Aggregate<\/code> is an extension of the <code>IMongoCollection<\/code>. Aggregate returns a type of <code>IAggregateFluent&lt;TDocument&gt;<\/code><strong>. <\/strong>All other operators like <code>SortBy<\/code>, <code>Group<\/code>, <code>Match<\/code>, <code>Project,<\/code> etc. do the same thing. They are extensions of <code>IAggregateFluent<\/code> and return <code>IAggregateFluent&lt;TDocument&gt;<\/code><strong>. <\/strong>This is the how methods chaining is accomplished which is really one of the characteristics of the fluent API. So, again, I will repeat the API is easy to use and difficult to misuse, and every method name is self-documenting.<\/p>\n\n\n\n<p>Take a look at <code>IAggregateFluent<\/code>, in the image below. Surrounded with red is a read-only property named <code>Stages<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"626\" height=\"198\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-126.png\" alt=\"\" class=\"wp-image-81401\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>It represents every operation performed on the <code>IMongoCollection<\/code>. If you set the breakpoint on the line<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;queryToExplain&nbsp;=&nbsp;query.ToString();<\/pre>\n\n\n\n<p>And try to examine the query variable, you will notice that there are six stages defined as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1219\" height=\"138\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-127.png\" alt=\"\" class=\"wp-image-81402\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Every stage has the type of <code>IPipelineStageDefinition<\/code> and has the Input and Output type as well as the shell operator name as shown in the image below. The .NET driver is perfectly mapped to MongoDB shell!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"878\" height=\"440\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-128.png\" alt=\"\" class=\"wp-image-81403\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>To capture the whole query, execute <code>query.toString();<\/code>. The query is saved in the article\u2019s solution in a file Query.js, located in Aggregation folder.<\/p>\n\n\n\n<p>The second way to accomplish the same task is to use LINQ like syntax. To do that, the <code>MongoDB.Driver.Linq<\/code> namespace must be included. This time the query looks similar like is shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var pipeline2 = collection.AsQueryable()\n    .GroupBy(z =&gt; new { z.TerritoryId, z.CustomerId })\n    .Select(g =&gt; new { TerritoryIdPlusCustomerId = g.Key, TotalDue = g.Sum(x =&gt; x.TotalDue) })\n    .OrderBy(o =&gt; o.TotalDue)\n    .GroupBy(o =&gt; o.TerritoryIdPlusCustomerId.TerritoryId)\n    .OrderBy(g =&gt; g.Key)\n    .Select(g =&gt; new\n    {\n        TerritoryId = g.Key,\n        MaxCustomer = new { Name = g.Last().TerritoryIdPlusCustomerId.CustomerId, g.Last().TotalDue }\n    })\n    .Where(x =&gt; x.MaxCustomer.TotalDue &gt; Limit)\n    .OrderByDescending(x =&gt; x.MaxCustomer.TotalDue);<\/pre>\n\n\n\n<p>As you see this time, the <code>AsQueryable<\/code> extension is used. This is an extension of the <code>IMongoCollection<\/code> and returns an instance of <code>IMongoQueryable<\/code>. Every method also returns <code>IMongoQueryable<\/code>, and this is the how method chaining is accomplished, this time with LINQ style syntax.<\/p>\n\n\n\n<p>Method names are similar to <code>IAggregateFluent<\/code>. Instead of <code>Group<\/code><strong>,<\/strong> there is <code>GroupBy<\/code>; instead of <code>Sort<\/code>; there is <code>OrderBy<\/code>; instead of <code>Project<\/code><strong>,<\/strong> there is <code>Select<\/code>; instead of <code>Match<\/code><strong>,<\/strong> there is <code>Where, <\/code>etc.<\/p>\n\n\n\n<p>You can also use SQL like syntax to accomplish the same task, as shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;pipeline&nbsp;=&nbsp;from&nbsp;o&nbsp;in\nfrom&nbsp;z&nbsp;in&nbsp;collection.AsQueryable()\ngroup&nbsp;z&nbsp;by&nbsp;new&nbsp;{&nbsp;z.TerritoryId,&nbsp;z.CustomerId&nbsp;}\ninto&nbsp;g\nselect&nbsp;new&nbsp;{&nbsp;TerritoryIdPlusCustomerId&nbsp;=&nbsp;g.Key,&nbsp;TotalDue&nbsp;=&nbsp;g.Sum(x&nbsp;=&gt;&nbsp;x.TotalDue)&nbsp;}\norderby&nbsp;o.TotalDue\ngroup&nbsp;o&nbsp;by&nbsp;o.TerritoryIdPlusCustomerId.TerritoryId\ninto&nbsp;g\norderby&nbsp;g.Key\nselect&nbsp;new\n{\n   TerritoryId&nbsp;=&nbsp;g.Key,\n   MaxCustomer&nbsp;=&nbsp;new\n   {&nbsp;Name&nbsp;=&nbsp;g.Last().TerritoryIdPlusCustomerId.CustomerId,&nbsp;g.Last().TotalDue&nbsp;}\n};\n\/\/&nbsp;filter&nbsp;by&nbsp;limit&nbsp;and&nbsp;apply&nbsp;descaning&nbsp;order&nbsp;\npipeline&nbsp;=&nbsp;pipeline.Where(x&nbsp;=&gt;&nbsp;x.MaxCustomer.TotalDue&nbsp;&gt;&nbsp;Limit).OrderByDescending(x&nbsp;=&gt;&nbsp;x.MaxCustomer.TotalDue);<\/pre>\n\n\n\n<p>There is a method to pass <code>BsonDocument<\/code> to the pipeline as well. In the solution the method name is <code>UsingMongoShellLikeSyntax<\/code>.<\/p>\n\n\n\n<p>The result from all three methods is displayed on the console output and shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"548\" height=\"255\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-129.png\" alt=\"\" class=\"wp-image-81404\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>At this point, I have to make two digressions. First, I briefly describe the <code>lookup<\/code> operator and then the <code>unwind<\/code> operator.<\/p>\n\n\n\n<p>As you recall when I write about schema design, the preferable way to work with data is embedded documents, but, there is a situation when you have to join data from a different collection. In such a situation, the <code>lookup<\/code> operator will help you.<\/p>\n\n\n\n<p>Switch the solution\u2019s startup object to be <em>SampleLookup<\/em> located in the <em>Aggregation<\/em> folder. This example creates two collections, one that contains names and the other that contains the meaning of the names. Of course, the only reason I am doing like this is to show how the <em>lookup<\/em> operator works.<\/p>\n\n\n\n<p>If you use the <em>peek definition<\/em> of Visual Studio, it will show what <code>Lookup<\/code> to expect, as shown in the image below, surrounded with red.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"989\" height=\"151\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-130.png\" alt=\"\" class=\"wp-image-81405\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The first <code>Lookup<\/code> is an extension of the <code>IMongoCollection<\/code>. It executes in the context of the collection and requires a foreign key collection as the first parameter, then the local field on which relation is established, the foreign field that composes the relation, and finally the result type. Unfortunately, the result type cannot be an anonymous type (or I did not discover how to be anonymous?). As always is expected that from the foreign collection will be returned more than one element, so, the operator always expects an array to be returned.<\/p>\n\n\n\n<p>In this case that looks like the code shown in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var result = await colPerson.Aggregate()\n    .Lookup&lt;Person, NameMeaning, LookedUpPerson&gt;(collNameMeaning, \n       x =&gt; x.FirstName, \n        y =&gt; y.Name,\n        x =&gt; x.Meanings\n).ToListAsync();<\/pre>\n\n\n\n<p>And the result is displayed on the console window as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"847\" height=\"149\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-131.png\" alt=\"\" class=\"wp-image-81406\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The MongoDB documentation states following for <code>unwind<\/code>: <em>Deconstructs an array field from the input documents to output a document for <\/em>each<em> element. Each output document is the input document with the value of the array field replaced by the element. <\/em><\/p>\n\n\n\n<p>That means if you want to aggregate on embedded documents, you have to promote them to the top level. Here\u2019s an example. If you would like to aggregate sales details, an array of documents embedded in the main document, you have to use <code>unwind<\/code>. The example of the basic usage of unwind operator could be found in the <em>SampleUnwind<\/em> solution file.<\/p>\n\n\n\n<p>If you take just one document in the <em>adventureWorks2016<\/em> collection by applying <code>Limit(1)<\/code> and after that apply <code>Unwind<\/code> on the <code>Details<\/code> field, the output will produce as many rows as the number of embedded documents that are in the <code>Details<\/code> fields. The source code to accomplish such a task is displayed in the snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var&nbsp;collection&nbsp;=&nbsp;SampleConfig.Collection;\nvar&nbsp;result&nbsp;=&nbsp;await&nbsp;collection.Aggregate().Limit(1)\n           .Unwind&lt;SalesHeader,&nbsp;SalesDetailHelper&gt;(x&nbsp;=&gt;&nbsp;x.Details)\n           .Project(x=&gt;new&nbsp;{x.Details.SalesOrderDetailId})\n           .ToListAsync();\n           foreach&nbsp;(var&nbsp;example&nbsp;in&nbsp;result)\n           {\n          Console.WriteLine($\"{example.SalesOrderDetailId.ToString().PadRight(10)}\");\n           }<\/pre>\n\n\n\n<p>And finally, make <em>AggregationUnwind<\/em> the startup object of the article\u2019s solution. There are five tests in this class. Two of them are accomplished by using LINQ, two of them by using IAggregateFluent and one by parsing <code>BsonDocument<\/code> as shown in the image below. The result is always the same and equal what is returned by executing the T-SQL script in SSMS.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"975\" height=\"453\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-132.png\" alt=\"\" class=\"wp-image-81407\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>I found that using LINQ style coding is extremely easy. Unwind in LINQ style syntax is simple <code>SelectMany<\/code> for joining, as shown in the image below highlighted with yellow.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"405\" height=\"367\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-133.png\" alt=\"\" class=\"wp-image-81408\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Using <code>IAggregateFluent<\/code> is a little bit difficult, especially when working with <code>Unwind<\/code>. <code>Unwind<\/code> has three different overloads. One is obsolete, one uses <code>BsonDocument<\/code> as output, and that means breaks strongly typed writing, and the last one is a little bit confusing.<\/p>\n\n\n\n<p>I expected that the result of the <code>UnWind<\/code> operation should be an anonymous type. Unfortunately, it should be a concrete type of class that is defined. It is shown surrounded with red on the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"573\" height=\"301\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-134.png\" alt=\"\" class=\"wp-image-81409\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>And <code>SalesDetailHelper <\/code>is defined as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"454\" height=\"138\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/10\/word-image-135.png\" alt=\"\" class=\"wp-image-81410\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Pretty simple, but on the other hand still a little bit annoying. It would be nice if you could use an anonymous type.<\/p>\n\n\n\n<p>The aggregation framework has limitations. The stages have a limit of 100 MB of RAM, per stage. If a stage exceeds the limit, MongoDB produces an error.<\/p>\n\n\n\n<p>Funny thing about this limitation is that I was unable to find how much memory is used per stage. Thanks to, the moderator in MongoDB forums, I finally found out that there are no possibilities to get that information. It will be available in the next release. As a drawback for such a situation, you could pass an optional parameter <code>allowDiskUse<\/code> to <code>true<\/code> to enable writing data to temporary files, as in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.adventureWorks2016.aggregate( [\n      { $project : .... },\n      { $sort : ... }\n   ],\n   { allowDiskUse: true }\n)<\/pre>\n\n\n\n<p>Another limitation is the ability to use indexes. I was trying to avoid the collection scan when using the <code>group<\/code> operator. Unfortunately using indexes with the <code>group<\/code> operator does not work. The operator always performs the scan. Furthermore, if in the aggregation pipeline, any stage cannot benefit from index usage, all stages that follow also will not use indexes.<\/p>\n\n\n\n<p>Besides that, everything seems to be excellent.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-summary\">Summary<\/h2>\n\n\n\n<p>There is no doubt, MongoDB is a great product. Although I still search for some features that exist in the SQL world, my general impression is excellent. I can say the same for the .NET driver. It is easy to use, every method (extension) emphasizes the intent of the code, enables you to write less code, and everything is where you expect to be.<\/p>\n\n\n\n<p>Although the article moves at the speed of light, I hope that the article with article\u2019s solution would be enough to encourage readers to start exploring MongoDB and the .NET driver.<\/p>\n\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs: How to program with MongoDB using the .NET driver<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. How do you connect to MongoDB from a C# application?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Install the MongoDB.Driver NuGet package, then create a MongoClient instance with a connection string: var client = new MongoClient(&#8220;mongodb:\/\/username:password@localhost:27017\/dbname&#8221;). From the client, access a database with GetDatabase() and a collection with GetCollection&lt;T&gt;(). The MongoClient handles connection pooling automatically.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. How does MongoDB compare to SQL Server for .NET developers?<\/h3>\n            <div class=\"faq-answer\">\n                <p>MongoDB stores data as flexible JSON-like documents (BSON) in collections rather than rows in tables. There\u2019s no fixed schema, so documents in the same collection can have different fields. The MongoDB .NET driver supports LINQ queries, so many query patterns translate directly from Entity Framework or Dapper. The biggest difference is data modeling: instead of normalizing across tables with joins, MongoDB encourages embedding related data within a single document.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. Can you use LINQ with MongoDB in .NET?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Yes. The MongoDB .NET driver includes a LINQ provider that lets you write strongly-typed queries using standard LINQ syntax: collection.AsQueryable().Where(x =&gt; x.Price &gt; 100).OrderBy(x =&gt; x.Name). The driver translates LINQ expressions into MongoDB\u2019s native query language. For more complex operations like aggregation pipelines, the driver provides a fluent builder API alongside LINQ.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use the MongoDB .NET driver with C#. Covers connecting to MongoDB, BSON type mapping, CRUD operations, LINQ queries, aggregation pipelines, and authentication &#8211; explained for SQL Server developers.&hellip;<\/p>\n","protected":false},"author":314795,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,159161],"tags":[5618],"coauthors":[47071],"class_list":["post-81370","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-mongodb","tag-mongodb"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/81370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/314795"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=81370"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/81370\/revisions"}],"predecessor-version":[{"id":108995,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/81370\/revisions\/108995"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=81370"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=81370"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=81370"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=81370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}