Introduction to MongoDb with .NET part 4: querying basics with find and findOne

In the previous post discussed some details around insertions in MongoDb. We saw that it was quite a painless and straightforward operation. We use the “db” handle, provide the name of the collection where we’d like to insert a document, call the “insert” function on it and pass in a JSON document. All MongoDb documents must have a unique and immutable ID represented by the “_id” field. By default it is of type ObjectId which comes from the BSON specification. We can also provide an ID of integer or string or some other type ourselves but then it is our responsibility that the ID is unique within the collection otherwise we’ll get an exception. Auto-incremented integer IDs are difficult to implement in MongoDb but storing GUID as a string for the ID is a viable option if you’d like to stick to a familiar ID setting strategy from relational databases.

In this post we’ll start looking into querying in MongoDb which will span multiple posts. We’ll mostly see a lot of short examples.

Querying with find

Querying means that we’d like to find some data in a collection. Sometimes we want to find all of them, or just some of them where we provide a filter. Occasionally we want to retrieve only a single document that matches a criteria. In other words we want to achieve something like…

“SELECT [column], [column] FROM [table] WHERE [condition]”

We’ve already seen an example for that in the form of the “find” function:

use loadtest
db.products.find()

If you followed along the examples in the previous post then the find() function without any filter will yield something like this:

So that corresponds to a “SELECT * FROM [table]” query with no WHERE clause.

Filtering is provided by way of another JSON document provided to the find function. E.g. if we want to retrieve all products where name is “tv” then we can write the following:

db.products.find({"name" : "tv"})

The above query will find one record, but if there were multiple documents with a field “name” and value “tv” we’d see them here. Soon we’ll import a larger data set into our database so that we can run more interesting queries. However, it’s important to start small where it’s easier to demonstrate the basics.

So that was a single WHERE clause. How do we enter multiple filters, like WHERE name = ‘tv’ AND stock_level = 50? We just need to extend the JSON query document:

db.products.find({"name" : "tv", "stock_level" : 50})

Which returns the same result as above.

What if we want to limit the number of fields returned? I.e. how do we perform a “SELECT name, stock_level FROM …” type of query in MongoDb? With another JSON document of course! We can supply a second JSON document after the JSON filter where we can specify which fields to show and suppress using “true” and “false” boolean values. The _id field is always shown by default so if we want to suppress it then we must specify that as follows:

db.products.find({"name" : "tv"}, {"_id" : false})

This returns…

{ "name" : "tv", "stock_level" : 50 }

…i.e. all fields except for the _id. If we only want to see the stock level and not anything else then we can write the following query:

This filter suppresses the “name” and any other fields by default, we don’t need to specify like “name” : false, “some_other_prop” : false in the field selector.

Querying with findOne

The function findOne is similar to find but it only returns a single document even if the filter matches multiple documents. A single random match will be returned by the function. findOne with no parameters will return a single document at random, we cannot tell for sure which, but the very first document is a safe bet. E.g. the query…

db.products.findOne()

…returns

{ "_id" : 1, "name" : "radio", "stock_level" : 100 }

We can provide the exact same parameters to this function as to the find function. Here comes an example:

The only difference is that findOne returns exactly one matching document even if there are many.

findOne() can help you get acquainted with the data set. We mentioned before that there’s no strict schema in MongoDb collections but in practice documents within a collection will follow some well defined structure. After all just because you can mix customers and products in a collection called “things” it doesn’t mean that you’ll ever do so in a real-life project. Wwe prefer well structured data records in our databases, right?

So if you’d like to view the schema of a collection, call findOne on it and you’ll be able to view its general structure, its properties, its types and its embedded documents.

Pretty JSON

I just wanted to mention that we can tell the Mongo client to present the JSON documents in a better format. We can attach the “pretty” function after find or findOne as follows:

Hello, most JSON queries can be expressed solely using the C# driver functions, i.e. with no direct JSON string input. As far as I can remember there are exceptions to this with complex queries such as aggregations but I’ll need to look up the driver’s capabilities myself as well in this regard. //Andras

My goal with this blog is to offend everyone in the world at least once with my words… so no one has a reason to have a heightened sense of themselves. We are all ignorant, we are all found wanting, we are all bad people sometimes.