Understanding MongoDB Queries

Working with the Official C# Client Driver for MongoDB can be quite rewarding as it makes it easy for the developer to interface with the Mongo Database.  For more information about MongoDB or the C# driver, please refer to the Official MongoDB website.

What I would like to share with you today is looking at the query that you are about to send to the MongoDB.  This can very useful when you, as a developer, are attempting to build your filter criteria.  We can do this by subscribing to the CommandStartedEvent.

Let me start by showing you a basic connection filtering of “Person” views that are stored in the “People” collection.

//  Simple query to find employees
var mongoConnectionString = @"mongodb://localhost";
var client = new MongoDB.Driver.MongoClient(mongoConnectionString);
var db = client.GetDatabase("Employees");

var peopleCollection = db.GetCollection<Person>("People");
var filter = Builders<Person>.Filter.Gt(f => f.EmployeeNumber, 4554);
var people = peopleCollection.Find(filter).ToList();

people.ForEach(person => Console.WriteLine(person.ToJson()));

client = null;
 

Simply using the C# driver’s Builder class, we cannot see the underlying query that is built from it. If we could see the built JSON then we could sent to the server. Here are two ways of getting the actual query so that you could run it in your favorite Mongo shell or client.

//  Output the query as JSON
var mongoConnectionString = @"mongodb://localhost";
var client = new MongoDB.Driver.MongoClient(mongoConnectionString);
var db = client.GetDatabase("Employees");

var peopleCollection = db.GetCollection<Person>("People");
var filter = Builders<Person>.Filter.Gt(f => f.EmployeeNumber, 4554);
var serializer = BsonSerializer.SerializerRegistry.GetSerializer<Person>();
var query = filter.Render(serializer, BsonSerializer.SerializerRegistry).ToJson();
Console.WriteLine(query);

client = null;
 

The resulting JSON output for the query variable would be the following:

{ "EmployeeNumber" : { "$gt" : 4554 } }
//  Output all queries as JSON based on the CommandStartedEvent
var mongoConnectionString = @"mongodb://localhost";
var settings = MongoClientSettings.FromUrl(new MongoUrl(mongoConnectionString));
settings.ClusterConfigurator = builder => 
	builder.Subscribe<CommandStartedEvent>(started => {
	//	Listen to the event here.
	var bsonDoc = started.Command;
	if (bsonDoc.Names.Contains("query"))
		Console.WriteLine(bsonDoc["query"].ToJson());
});
var client = new MongoClient(settings);
var db = client.GetDatabase("Employees");
var peopleCollection = db.GetCollection<Person>("People");
var filter = Builders<Person>.Filter.Gt(f => f.EmployeeNumber, 4554);
var people = peopleCollection.Find(filter).ToList();

client = null;
 

The resulting JSON output for the query variable would be the following:

{ "EmployeeNumber" : { "$gt" : 4554 } }

Why should I wire up a command handler when I get the same information from rendering the filter itself just by using the BsonSerializer? If you use the BsonSerializer, you would have to do so for every query that you write. Wiring up the CommandStartedEvent allows you to inspect all of the queries along with other data that you might be interested. If you couple this with your favorite log writer, you can write information out to your log file to help you determine the problem with an issue occurs.

I know this is a basic example, and I will create a more in depth example if needed. Please let me know if this helped you by dropping me a line below. Until next time.

Advertisements

Leave a Reply

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

WordPress.com Logo

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

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s