MongoDB - Advanced Data Retrieval
In the last article we learned about a little more sophisticated data retrieval, and in this article we’ll take the whole thing one step further and learn about some advanced data retrieval methods.
First off—projection. Though it may sound a bit threatening, the truth is it’s really quite simple. In short, the idea is to take the data you need, and only that data. If we translate this to MySQL, instead of using SELECT *, we use a more precise selection—and if you’ve ever written queries in MySQL then this shouldn’t scare you.
So what are we talking about here? Well, we don’t always want to receive the entire object. Let’s look at for example collection clients which we worked with in the previous article, with instructions for creating them. What does it look like? A hundred of something like this:
{ "_id" : ObjectId("541d9aee784269c2e9f3c092"), "x" : 17, "name" : "gIZxF4ALvwiMMtvtZC8G6ExsmxQum8KFAQws4z6un9nMrol8QCCue7T7rCLVvnNM0dfVzW3VKZgEeS5PLKA6RNI7lZbWT1ySl8v1xb77nmCasF3I8Vr5Vu3Bqa0uDv8umXkbreihE1DXl2OrudxEmUPMf0PKSdQhHe5zqqQ90LOBBwd6lNBGhmeLkI1ramDC4i7JnnfmTrX8v61e", "value" : 34.991921903565526 }
{ "_id" : ObjectId("541d9aee784269c2e9f3c093"), "x" : 18, "name" : "e683H4QlB2sHLGUtvnftDpWQTJJgZ2Ev92TRTEK5oiCbLxsz2d5tS0hx4fKZqzfITMrtlDJkI4R2RRMhvT4wngOulcTnb9t8SnfDytSIplJUhly", "value" : 25.878882687538862 }
{ "_id" : ObjectId("541d9aee784269c2e9f3c094"), "x" : 19, "name" : "HIIWTKsT8guLtyMkgf3KVmCzJNUviArxVT9GaT4vI3Bkg3AZLWzMoMGVynoQz1qp0elVk0oyxdx7fUUFFRWNRtUJipf95WhKGQu3UDkRb2XFigmuhGnVc5WNbCg1w", "value" : 96.42805075272918 }
Let’s assume we want to find the document with the ID of 541d9aee784269c2e9f3c092. I’ll remind you that we’re talking about an ID that MongoDB gives out automatically to documents. If you’ve gone through the other articles in the series it won’t surprise you to hear that you can receive the object using a find query like so:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")});
Using the ObjectId method is necessary if we use an ID like this. But there’s nothing surprising here. When we run something like this we get back the entire document.
{ "_id" : ObjectId("541d9aee784269c2e9f3c092"), "x" : 17, "name" : "gIZxF4ALvwiMMtvtZC8G6ExsmxQum8KFAQws4z6un9nMrol8QCCue7T7rCLVvnNM0dfVzW3VKZgEeS5PLKA6RNI7lZbWT1ySl8v1xb77nmCasF3I8Vr5Vu3Bqa0uDv8umXkbreihE1DXl2OrudxEmUPMf0PKSdQhHe5zqqQ90LOBBwd6lNBGhmeLkI1ramDC4i7JnnfmTrX8v61e", "value" : 34.991921903565526 }
> db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")});
But what happens if we just need the name? We’ve no use for the entire document. And if we’re talking about a long and tiring document, chances are good that it will be very wasteful to pass all that information. So what do we do? Well, something like this:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")},{name:true});
We simple pass another argument that is a helpful object in which we write true next to each attribute of the document that we want. If we want more? No problem, we can pass something like this:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")},{name:true, x:true});
This way we get exactly what we want. Didn’t I promise that projection would be easy?
And if we’re already talking about easy things, let’s talk about sorting. Often, if we receive a few documents, we want to receive the list in order. For example, if we want all those that have an x smaller than 5, we want to receive them not in the order in which they were entered into the collection, but rather in alphabetical order according to their name. Just for things like this is why we need sorting for the results. With MongoDB is easy and straightforward. All we need to do is add a method after the find. We call this method sort and its argument is an object that contains two attributes: the first is the name of the field according to which we are sorting, and the second is 1 or -1 — for descending or ascending order. For example:
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":1});
In this case we’re sorting according to name all of the results of all the clients whose x is less than 5. Those of you with eagle eyes may notice that we use projection as well, ‘cause we don’t want to get all of those objects. If we didn’t want projection it would look like so:
db.clients.find({x:{$lt:5}}).sort({"name":1});
Sorting is also pretty easy, right? Same thing with LIMIT. We use limit in a lot of cases. For example, many times we only want, say the first 50 entries and the rest doesn’t interest us. If we take the query above—well, let’s say we only want the top two after sorting. How do we do this? We simply add the limit method that gets a number. Which number? The number that we want. So here’s the example you’ve been waiting for.
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":-1}).limit(2)
Again, pretty easy right? That’s how we concatenate the methods (which is pretty similar to jQuery of course, but not only). Good times all around. And if we want an OFFSET, which is basically just skipping a few results and starting the restriction from the second result (really useful for layouts e.g. getting the results for 1-10, then 11-20, and so on) then we use the skip method which also gets a number:
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":-1}).limit(2).skip(2);
And if you’ve read this entire guide until this point, including this—then the line of code above shouldn’t look too threatening. ‘Cause all in all there is a db (remember that we used use on it?) and then the collection, and then find which receives a conditional object and we also tell it exactly what we want it to see (in this case the name and the x). The results we then sort with descending order according to the name, get only 2 results (even though there are more) thanks to the LIMIT, but we don’t get the actual first two results but rather the following two because of the skip.
OK, so maybe it is a little threatening—it would pay to practice a bit so it looks a bit less diabolical.
In the next article we’ll talk about updating data in MongoDB.
About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment