Mongo Query to access an embedded document from an Array of Subdocuments

In our company we use Mongo DB as our data store to store all our data. I'm very new to the concept of NoSQL DB and Mongo myself. Today one of my colleagues in the QA team asked me "how to query and access just the first element in a field, that is an array of embedded documents?" Interesting! I thought. So, I set out to explore a little.

I had heard of the projection concept from another colleague before. It gives you the first match out of all the elements that match your given query. Had glanced over it for a few minutes before. The $ symbol and all! So, it got me thinking, would it be useful in this situation?

Lets say we have a collection named "order", and a field named "items", which is an array of subdocuments. So, for a given order ID, we need to get the first item from the array of items. First we started out with fetching just the items field from the collection:

db.getCollection('order').find({id:12345, "items" : {$exists: true}}, {"items":1})

This query gave us a result that contain the "id" and "items" fields as the result. The "id" was an unnecessary result here. So, we removed that next:

db.getCollection('order').find({id:12345, "items" : {$exists: true}}, {"items":1, _id: 0})

Now, we had just the "items" field in the result and this field is the array of subdocuments we were interested in. The next step was to access just the subdocument at index 0 of this array.

This particular document in the Mongo doc spoke about how to match a specific element in a field that is an array of subdocuments. But, we did not have to match any specific element and needed the whole document itself. So, we then tried this next query, hoping that it would return the subdocument at the first index of the array:

db.getCollection('order').find({id:12345, "items.0" : {$exists: true}}, {"items": 1, _id: 0})

But this returned the same result as the previous query. It totally made sense. The query read, "return the list of items if there exists an element at index zero of the array".

Now, we had to somehow print (may be a wrong word to use here) just the first element from the array. This is where projection came in handy. This is what Mongo documentation says about the use of projection:

"The positional $ operator limits the contents of an from the query results to contain only the first element matching the query document."

Our query's matching criteria above was based on "items.o", so we now had to just project it and we did so using the following query:

db.getCollection('order').find({id: 12345, "items.0" : {$exists: true}}, {"items.$":1, _id : 0})

Notice the .$ in the query. This tells Mongo to project the element that matches the query document. So now, the result was just the subdocument at index 0 of the "items" field. We could now access the subdocument at any index by modifying the index in the query.

db.getCollection('order').find({id: 12345, "items.index" : {$exists: true}}, {"items.$":1, _id : 0})

Hope this helps someone else too!

Cheers!

  • Happy to hear from you if there's any other way to solve this, or if you find any mistakes, or have suggestions, etc.