$project in MongoDB - What is $project and how to use it in MongoDB
Introduction
In this article we’ll be discussing the stage of $project in MongoDB. We’ll explain it from the ground up so if you don’t know what a stage is please keep reading because we’ll cover that also.
Prerequisites
If you want to follow along with the demos you’ll need to have MongoDB installed on your system. You can either follow along through the MondoDB console or some interface like Compass Community.
The Pipeline Concept
The pipeline concept is similar to what you might be familiar with in the Unix Shell. You might execute a command and take that commands output as the input to the next command. It looks something like this in the Shell:
1 | command_1 | command_2 | command_3 | .... | command_N |
Where the output of command_1 is “piped” into command_2, whose output is “piped” into command_3 and so on.
This same concept exists within MongoDB’s aggregation. There are a set of stages, and each stage takes in a set of documents are outputs a set of documents. The output of one stage is used as the input to the next stage, same as in “piping”.
The stages that occur during aggregation are $project, $match, $group, $sort, $skip, $limit, and $unwind. Let’s take a look at what each one does starting with our focus $project.
- $project − Selects specific fields
- $match − Filters documents by some criteria
- $group − Performs the actual aggregation
- $sort − Sorts the documents by some criteria
- $skip − Used to skip ahead in the array of documents
- $limit − Limits the amount of documents returned
- $unwind − This is a stage that deals with array fields and is a little hard to explain without visually seeing it, so please refer to the documentation if you’re curious about this field.
What’s done on the $project stage of aggregation
Let’s elaborate some more on what the $project stage does in aggregation. $project lets you specify what fields you want to have returned in the documents returned by your aggregation. This is not limited to existing fields but can include new fields that are computed.
How to Specify to Include a Field
To specify a field you want to include you can use this syntax:
1 | <field>: true |
or
1 | <field>: 1 |
So if you want the firstname
to be included in the documents, then you would use
1 | firstname: true |
or
1 | firstname: 1 |
We think most developers learn by example so let’s jump straight into an example. Locally we have a sample database grocerydb
for a small grocery store. Inside grocerydb
is a products
collection that contains the following three documents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | > use grocerydb switched to db grocerydb > db.products.find() { "_id" : ObjectId("5d12c9974b74efae4662b8df"), "name" : "Soda", "quantity" : 10, "price" : 5.5 } { "_id" : ObjectId("5d12c9a34b74efae4662b8e0"), "name" : "Bread", "quantity" : 9, "price" : 2.5 } { "_id" : ObjectId("5d12c9b24b74efae4662b8e1"), "name" : "Milk", "quantity" : 4, "price" : 3.5 } |
To use an aggregation and get the quantity field back we could use a query like this:
1 | db.products.aggregate( [ { $project : { quantity : true } } ] ) |
Which would return:
1 2 3 | { "_id" : ObjectId("5d1a53765475803d1d2950b8"), "quantity" : 10 } { "_id" : ObjectId("5d1a53ce3eb9103d1d1a7981"), "quantity" : 9 } { "_id" : ObjectId("5d1a53d03eb9103d1d1a7982"), "quantity" : 4 } |
How to Omit the _id field
Now you saw in the last example that even though the _id wasn’t specified in $project but was returned. This is because _id field is returned by default but you can omit the field by using this in your $project specification:
1 | _id: false |
or
1 | _id: 0 |
Let’s see how we’d modify the last example to omit the id:
1 | db.products.aggregate( [ { $project : { quantity : true, _id: false } } ] ) |
Which returns the following documents:
1 2 3 | { "quantity" : 10 } { "quantity" : 9 } { "quantity" : 4 } |
How to Add a New Field
Now let’s try using $project to add a new field to our aggregation. For a simple example we’ll create a new field withTax
for the price with sales tax at 8.25%. We’ll also add the name back in so you can verify the product with the price.
1 2 3 4 5 6 7 | db.products.aggregate( [ { $project : { name: true, quantity : true, _id: false, withTax: {$multiply: ["$price", 1.0825]} } } ] ) |
This is the result:
1 2 3 | { "name" : "Soda", "quantity" : 10, "withTax" : 5.95375 } { "name" : "Bread", "quantity" : 9, "withTax" : 2.70625 } { "name" : "Milk", "quantity" : 4, "withTax" : 3.7887500000000003 } |
Conclusion
We explained what $project does in aggregation and how to use it. We also went through an example of specifying a field, omitting the _id, and creating a computed field. We’ll leave it to you to explore using some of the other stages along with the $project stage to see what you can do.
If you want put your data and database management in the hands of someone you can trust, please don’t hesitate to reach out to us at Object Rocket.
Pilot the ObjectRocket Platform Free!
Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.
Get Started