Using LINQ to Query MongoDB in a .NET Core Application
Rate this tutorial
If you've been keeping up with my series of tutorials around .NET Core and MongoDB, you'll likely remember that we explored as well as . Neither of these previously explored subjects are too difficult, but depending on what you're trying to accomplish, they could be a little messy. Not to mention, they aren't necessarily "the .NET way" of doing business.
This is where LINQ comes into the mix of things!
With Language Integrated Queries (LINQ), we can use an established and well known C# syntax to work with our MongoDB documents and data.
In this tutorial, we're going to look at a few LINQ queries, some as a replacement to simple queries using the MongoDB Query API and others as a replacement to more complicated aggregation pipelines.
To be successful with this tutorial, you should already have the following ready to go:
While this tutorial is part of a series, you don't need to have read the others to be successful. However, you'd be doing yourself a favor by checking out the other ways you can do business with .NET Core and MongoDB.
To keep this tutorial simple and easy to understand, we're going to create a new console application and work from that.
Execute the following from the CLI to create a new project that is ready to go with the MongoDB driver:
For this tutorial, our MongoDB Atlas URI string will be stored as an environment variable on our computer. Depending on your operating system, you can do something like this:
The Atlas URI string can be found in your MongoDB Atlas Dashboard after clicking the "Connect" button and choosing your programming language.
Open the project's Program.cs file and add the following C# code:
In the above code, we are explicitly saying that we want to use LINQ Version 3 rather than Version 2, which is the default in MongoDB. While you can accomplish many LINQ-related tasks in MongoDB with Version 2, you'll get a much better experience with Version 3.
We're going to take it slow and work our way up to bigger and more complicated queries with LINQ.
In case you've never seen the "sample_mflix" database that is part of the sample datasets that MongoDB offers, it's a movie database with several collections. We're going to focus strictly on the "movies" collection which has documents that look something like this:
There are quite a bit more fields to each of the documents in that collection, but the above fields are enough to get us going.
To use LINQ, we're going to need to create mapped classes for our collection. In other words, we won't want to be using
BsonDocumentwhen writing our queries. At the root of your project, create a Movie.cs file with the following C# code:
We used a class like the above in our previous tutorials. We've just defined a few of our fields, mapped them to BSON fields in our database, and told our class to ignore any extra fields that may exist in our database that we chose not to define in our class.
Let's say that we want to return movies that were released between 1980 and 1990. If we weren't using LINQ, we'd be doing something like the following in our Program.cs file:
However, since we want to use LINQ, we can update our Program.cs file to look like the following:
In the above code, we are getting a reference to our collection and creating a LINQ query. To break down the LINQ query to see how it relates to MongoDB, we have the following:
- The "WHERE" operator is the equivalent to doing a "$MATCH" or a filter within MongoDB. The documents have to match the criteria in this step.
- The "SELECT" operator is the equivalent to doing a projection or using the "$PROJECT" operator. We're defining which fields should be returned from the query—in this case, all fields that we've defined in our class.
To diversify our example a bit, we're going to change the match condition to match within an array, something non-flat.
Change the LINQ query to look like the following:
A few things changed in the above code along with the filter. First, you'll notice that we are matching on the
Castarray as long as "Michael Keaton" exists in that array. Next, you'll notice that we're doing a projection to only return the movie title and the movie plot instead of all other fields that might exist in the data.
We're going to make things slightly more complex now in terms of our query. This time we're going to do what would have been a MongoDB aggregation pipeline, but this time using LINQ.
Change the C# code in the Program.cs file to look like the following:
In the above LINQ query, we're doing a series of steps, just like stages in an aggregation pipeline. These stages can be broken down like the following:
- Match all documents where "Ryan Reynolds" is in the cast.
- Unwind the array of cast members so the documents sit adjacent to each other. This will flatten the array for us.
- Do another match on the now smaller subset of documents, filtering out only results that have "Ryan Reynolds" in them.
- Group the remaining results by the cast, which will only be "Ryan Reynolds" in this example.
- Project only the group key, which is the cast member, and the sum of all the movie runtimes.
If you haven't figured it out yet, what we attempted to do was determine the total amount of screen time Ryan Reynolds has had. We isolated our result set to only documents with Ryan Reynolds, and then we summed the runtime of the documents that were matched.
You just got a taste of LINQ with MongoDB in your .NET Core applications. While you don't have to use LINQ, as demonstrated in a few previous tutorials, it's common practice amongst C# developers.