Recently I had an interesting MongoDB query that I wanted to write. I had a document that contained a list, and I wanted to query a specific item out of the list, returning only the fields that I wanted. Here’s a similar dataset:
In this example, many different records may be created under the same SetId (with the MongoDB _id serving as the unique key). So, say, I want to query the database to see if a specific country and state exist in any document given SetId.
There’s lots of examples of how to do this with the json syntax, but C# provides this nifty fluent API… so it kind of makes sense to use that if I can. It took me awhile, but here’s what I came up with.
Dang. So you can see why it took me awhile. But, breaking it down helps (a little):
Aggregate
Starts a pipeline of operations to perform on the data. Essentially, you can list out a bunch of different steps to take and execute on the data sequentially. This lets the database do the work. In our example, we’re matching documents with the correct SetId, then looking at their Attributes list, and then making further filters from there.
Match
This is just a simple filter of the data. We’re asking for only documents where the SetId matches the one provided in to the function.
Project
Creates a subset of the data. This is especially useful if your document has a ton of different fields on it, but you only care about a few. If you’re planning on sending it all the way back out through a web request, for example, you might care about the size of the resulting dataset. In our case, we’re only looking at the specific properties we want in the Attributes list.
Unwind
This is essentially a “foreach” in Mongo. It takes the list and flattens it – essentially returning a document where the list is replaced by the individual item in the list. The document will have copies of all of the other data on its parent document, so you can access those properties, too. In our case, we are really only looking for a property that is on a list item.
Match
Again, this is just a filter. Now that we’ve unwound the list, we can just match the property that we want and query it accordingly.
AnyAsync
Finally, because we’re just looking for the existence/nonexistence of the item, we can just leverage AnyAsync, which works similar to Linq in that it will return true as soon as it finds any item. This could be useful if there are multiple documents that satisfy your query – it will short-circuit the deep query and just return as soon as it finds one.
Hopefully just seeing a nice example in C# will help with any future queries you might need to write! There seems to be a lack of solid, C# fluent api examples, so I’m hoping to just document some of the more interesting ones I come across here.