MongoDB Projections

While MongoDB is well known or fast lookups and search queries, even simple reads are subject to performance hits with larger data sets. As documents grow over time, it takes longer to retrieve them from collections. Documents can grow to a point where it makes more sense to partially return only the fields you want from a particular query. By "cherry picking" the fields you want returned, you can drastically improve performance. In this article, we demonstrate how to control return objects in MongoDB

Why Use Projections?

Take the following MongoDB query:

db.collection.find({a:3});

This simple read query will find any document in the collection where a = 3. Assuming there are no errors, this query will return the full document for each match. While this find query is pretty straightforward, it doesn't filter out the returned results at all. What if you only wanted to return specific attributes for each document? You may want to exclude certain attributes if they are lengthy (such as an array subdocument with hundreds of thousands of records) or attributes with sensitive information (passwords, credit card info, etc).

To control what is returned, you can use projections to dictate specifically what you want returned in the result set. For basic queries like find, you can do the following:

db.collection.find({a:3},{b:0});

Notice how we've supplied an optional argument {b:0} to filter what is returned. In this projection statement, we indicate that the query should return the a attributes for each matching document but exclude the b attribute from the result set. We indicate whether or not to return attributes based on 1 or 0 (true or false). Any attributes not explicitly referenced in the projection statement will be included by default.

NOTE: When using projections, you must be consistent with your inclusions or exclusions. You can't mix and match things to include with things not to include. In other words, define either what you want to return or what you do NOT want to return. Things like {b:0, a:1} won't work.

Using projections with write operations

Similar to read queries, you can use projections to filter result sets from write operations as well. Take the following example:

db.collection.findOneAndUpdate(
  {a:"some string"},
  {$set:{a:"another string"}},
  {projection:{b:0}}
)

In the above example, our first argument is the query (or criteria) for the record we want to update. The next parameter is our update function. The third contains our projection where we specify to omit the b attribute from the returned response. Please note that the same rules apply. We either specify fields to include (1) or fields to exclue (0) but not both.

Conclusion

Using projections may not seem practical at first but as your database grows you will want to control what you are bringing back with each successful read/write operation. By controlling the returned results, you can improve performance and dictate exactly what fields will be brought back from your MongoDB queries.

Your thoughts?