MongoDB allows us to store some pretty large, detailed documents in our collections. When we run queries on these collections, MongoDB returns whole documents to us by default. These documents may store deeply nested arrays or other embedded documents, and because of the flexible nature of MongoDB data, each might have a unique structure. All of this complexity can make these documents a challenge to parse, especially if we’re only looking to read the data of a few fields.
Fortunately, MongoDB allows us to use projections in our queries to specify the exact fields we want to return from our matching documents. To include a projection, we can pass a second argument to the .find()
method, a projection
document that specifies the fields we want to include, or exclude, in our returned documents. Fields can have a value of 1
, to include that field, or 0
to exclude it.
Let’s take a closer look at the syntax for projection
documents below:
db.<collection>.find( <query>, { <projection_field_1>: <0 or 1>, <projection_field_2>: <0 or 1>, … } )
Consider a document from the listingsAndReviews
collection that we’ve been working with. Each document in the collection shares a similar structure to the one below:
{ _id: ObjectId("5eb3d668b31de5d588f4292a"), address: { building: '2780', coord: [ -73.98241999999999, 40.579505 ], street: 'Stillwell Avenue', zipcode: '11224' }, borough: 'Brooklyn', cuisine: 'American', grades: [ { date: ISODate("2014-06-10T00:00:00.000Z"), grade: 'A', score: 5 }, { date: ISODate("2013-06-05T00:00:00.000Z"), grade: 'A', score: 7 }, { date: ISODate("2012-04-13T00:00:00.000Z"), grade: 'A', score: 12 }, { date: ISODate("2011-10-12T00:00:00.000Z"), grade: 'A', score: 12 } ], name: 'Riviera Caterer', restaurant_id: '40356018' }
You can imagine how viewing up to 20 documents just like this one, inside of a terminal, could easily get overwhelming.
If we were to query this collection and were just interested in viewing the address
and name
fields, we could run the following query that includes a projection:
db.listingsAndReviews.find( {}, {address: 1, name: 1} )
This would return the address
and name
fields for any documents that match our query. Our output for each document would look as follows:
{ _id: ObjectId("5eb3d668b31de5d588f4292a"), address: { building: '2780', coord: [ -73.98241999999999, 40.579505 ], street: 'Stillwell Avenue', zipcode: '11224' }, name: 'Riviera Caterer' }
Notice how, by default, the _id
field is included in our projection, even if we do not specify to include it.
But what if we’re not interested in seeing the _id
field? We can omit it from our results by specifying the _id
field in our projection
document. Instead of setting its value to 1
, we’d set it to a value of 0
to exclude it from our return documents.
db.listingsAndReviews.find( {}, {address: 1, name: 1, _id: 0} )
In some scenarios, we may need our query to return all the fields, except a select few. Rather than listing the fields we want to return, we can use a projection to define which fields we want to exclude from our matching documents by assigning the fields a value of 0
. For example, if we wanted to query our collection and see all fields but the grades
field, we could run the following command:
db.restaurants.find( {}, {grades: 0} )
It is important to note that except for the _id
field, it is not possible to combine inclusion and exclusion statements in a single projection document. For example, the following query with a projection would be invalid, and return a MongoServerError
:
db.restaurants.find({}, {grades: 0, address: 1 })
Before we wrap up the lesson, let’s practice writing queries with projections!
Instructions
Connect to the restaurants
database, then using the same listingsAndReviews
collection as the previous exercises, run a query to get a list of restaurants where the borough
is "Bronx"
. Use a projection to return the _id
, name
, and cuisine
fields from each matching document.
Query the listingsAndReviews
collection again. This time, your query should get all documents in the collection and return all fields except for the address
and grades
fields.