Introduction to MongoDb with .NET part 17: various query related functions


In the previous post we started looking into the querying techniques exposed by the MongoDb .NET driver. We looked at two ways of building queries: filter definition builders and LINQ-style queries. Filter definition builders are more powerful in my experience, meaning that they offer more complex querying techniques than the LINQ-style version. We applied the filters to the Find extension method that can be attached to a Mongo collection represented by the IMongoCollection of T interface. There are other find-related methods in the driver, called FindSync and its awaitable counterpart FindAsync but I think the Find extension method is more flexible.

In this post we’ll look at various query-related functions that can be attached to our searches. They correspond to a number of functions we looked at earlier while working in the Mongo shell: counting, limiting, skipping and sorting.

Counting the results

This is an easy one. Remember the count() JavaScript function to return the number of elements returned by a query? Not surprisingly there’s a Count() function to perform the same operation in the driver. It can be attached to the Find extension function like here:

ModelContext modelContext = ModelContext.Create(new ConfigFileConfigurationRepository(), new AppConfigConnectionStringRepository());
var boroughFilter = Builders<RestaurantDb>.Filter.Eq(r => r.Borough, "Brooklyn");
long restaurantsInBrooklyn = modelContext.Restaurants.Find(boroughFilter).Count();

The result will tell me that there are 6086 restaurants in Brooklyn in the collection. Count() also has an asynchronous version CountAsync.


Paging is done with the Skip and Limit functions that both accept an integer parameter:

var restaurantsInBrooklyn = modelContext.Restaurants.Find(boroughFilter).Skip(10).Limit(10).ToList();


There are two styles of syntax to define the sorting algorithm like in the case of filtering: a LINQ style and a definition builder style except that the definition is now called SortDefinition and not FilterDefinition. Sorting definitions are constructed in much the same way as filter definitions. Let’s take the first 5 restaurants and sort them by their restaurant IDs, i.e. not the default _id field but the restaurant_id one:

var idSortDefinition = Builders<RestaurantDb>.Sort.Ascending(r => r.Id);
var restaurantsInBrooklyn = modelContext.Restaurants.Find(boroughFilter).Limit(5).Sort(idSortDefinition).ToList();

The Sort property of the Builders is a gateway to build sort definitions, much like the Filter property helps us build filter definitions. The Linq expression selects the field by which to sort the result set.

The Sort property exposes a Descending method as well and you’ll probably guess what it does. Another important method is called Combine where we can define multiple sorting algorithms. Let’s try that on the zipcodes collection and sort the places by state in ascending and then by name in descending order:

var idSortDefinition = Builders<RestaurantDb>.Sort.Ascending(r => r.Id);
var zipSortByState = Builders<ZipCodeDb>.Sort.Ascending(z => z.State);
var zipSortByName = Builders<ZipCodeDb>.Sort.Descending(z => z.City);
var combinedSort = Builders<ZipCodeDb>.Sort.Combine(zipSortByState, zipSortByName);
var first100zips = modelContext.ZipCodes.Find(z => true).Limit(100).Sort(combinedSort).ToList();

Combined sorts can also be achieved with the Ascending and Descending extension methods that can be attached to the sort definition builders. Here’s an alternative solution:

var zipCombinedSortAlternative = Builders<ZipCodeDb>.Sort.Ascending(z => z.State).Descending(z => z.City);
var first100zipsAlternative = modelContext.ZipCodes.Find(z => true).Limit(100).Sort(zipCombinedSortAlternative).ToList();

The LINQ-style solution is implemented by the SortBy and SortByAscending extension methods that in turn can be attached to the Find extension method. Combined queries can be built using the ThenBy and ThenByDescending extension methods. Here’s the LINQ-equivalent of the above example:

var first100zipsLinqSolution = modelContext.ZipCodes.Find(z => true).Limit(100).SortBy(z => z.State).ThenByDescending(z => z.City).ToList();

That’s about it really, there’s not much else to say about these functions, they are quite simple.

In the next post we’ll look at insertions.

You can view all posts related to data storage on this blog here.


About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


A great site

iReadable { }

.NET Tips & Tricks

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: