$project in MongoDB

Introduction

There are methods such as find and findOne that are used to retrieve data from a MongoDB collection. We can always use projection to specify the fields we want returned in the output. The $project function in MongoDB is used to specify the fields in a document that are passed to the next stage of the pipeline. The fields can be the existing ones or new ones.

The project function can be used in a number of ways. We can specify any number of fields we need. We can also specify fields from an embedded document and even we can add new computed fields. In this article, we will discuss how to use $project in MongoDB.

$project in MongoDB

Let’s start with an example. Say we have the following documents in the details collection

> db.details.find().pretty()
{
        "_id" : ObjectId("5d70cb0d5c2e8e196c8e47ec"),
        "name" : "John",
        "age" : 21,
        "locations" : {
                "location1" : "New York",
                "location2" : "Chicago"
        }
}
{
        "_id" : ObjectId("5d70cb285c2e8e196c8e47ed"),
        "name" : "Sam",
        "age" : 23,
        "locations" : {
                "location1" : "Texas",
                "location2" : "New York"
        }
}
{
        "_id" : ObjectId("5d70cb395c2e8e196c8e47ee"),
        "name" : "Lisa",
        "age" : 25,
        "locations" : {
                "location1" : "Texas",
                "location2" : "Detroit"
        }
}
>

There are three documents each containing three fields – _id, name, age, and one embedded document – locations. Let’s see how can we use the $project function on the details collection.

Including specific fields in the output

To include the specific fields in the output, we need to specify the field names with the $project function Each field name should have 1 as its value.

> db.details.aggregate([ { $project : {name:1, age: 1}}])
{ "_id" : ObjectId("5d70cb0d5c2e8e196c8e47ec"), "name" : "John", "age" : 21 }
{ "_id" : ObjectId("5d70cb285c2e8e196c8e47ed"), "name" : "Sam", "age" : 23 }
{ "_id" : ObjectId("5d70cb395c2e8e196c8e47ee"), "name" : "Lisa", "age" : 25 }
>

We have to use aggregate. Here we specified two fields – name and age. In the output, we have the name and age of all the documents but there is one extra field also – _id. Remember, by default, the _id field will always appear in the output. But there is a way to exclude the _id field in the output.

Excluding the _id field

To exclude the _id field, all we need is to specify the _id field in the project function and set it to 0.

> db.details.aggregate([ { $project : {_id: 0, name:1, age: 1}}])
{ "name" : "John", "age" : 21 }
{ "name" : "Sam", "age" : 23 }
{ "name" : "Lisa", "age" : 25 }
>

Observe the output now. There is no _id field.

Including specific fields from an embedded document

In the details collection, each document has one embedded document – locations. This embedded document has two fields in it – location1 and location2. We can also have these fields in the output using the project function but there is a different procedure for this.

To get the fields from the embedded document, we need to specify the path in double quotes. For example, If we want the location1 field of the location embedded document, we will write something like this – “location.location1”. And we need to put this in double quotes, or else it result in a syntax error.

> db.details.aggregate([ { $project : {_id: 0, "locations.location1" : 1}}])
{ "locations" : { "location1" : "New York" } }
{ "locations" : { "location1" : "Texas" } }
{ "locations" : { "location1" : "Texas" } }

This is how we get the fields from an embedded document. (Note: There are no _id fields in the output because we set _id to 0 in the project function)

Including a computer field

In the details collection, Each document has – name, age and locations and of course _id fields. Suppose, we want the name field in the output along with a new field – primaryLocation. But there is no primaryLocation field in any document of details collection. Then how it is possible to get this field in the output? It is possible by using the project method and computing a value from the same document.

We want the primaryLocation in the output. We can give the value of location1 field of the embedded document, location, that is present in each document.

> db.details.aggregate([ { $project : {_id: 0, name: 1, primaryLocation : "$locations.location1"}}])
{ "name" : "John", "primaryLocation" : "New York" }
{ "name" : "Sam", "primaryLocation" : "Texas" }
{ "name" : "Lisa", "primaryLocation" : "Texas" }
>

Observe the output. Along with the name field, we have a new field, i.e. primaryLocation in the output. We used the following syntax.

primaryLocation: "$locations.location1";

We need to write the name of the field whose value we want to give to the new field in double-quotes starting with a dollar ($) sign. Although the location1 field is in the embedded document, but do not get confused, we need to write the field name in double-quotes even if it is not inside an embedded document.

Note: This newly added field only appears in the output, it won’t be added to the actual documents.

Conclusion

We have covered many uses of $project in MongoDB and hope you can apply what you’ve learned here to your application. Thanks and stick around for more tutorials from Object Rocket.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.