Retrieving a Subset of Fields

By default on a find operation, the entire object is returned. However we may also request that only certain fields be returned. This is somewhat analogous to the list of [column specifiers in a SQL SELECT statement (projection).

// select z from things where x="john"
db.things.find( { x : "john" }, { z : 1 } );

Field Negation

We can say "all fields except x" – for example to remove specific fields that you know will be large:

// get all posts about 'tennis' but without the comments field
db.posts.find( { tags : 'tennis' }, { comments : 0 } );

The _id Field

The _id field will be included by default.

If you do not want it, you must exclude it specifically. (Typically you will want to do that if using the covered index feature described below.)

// get all posts about 'tennis' but without the _id field
db.posts.find( { tags : 'tennis' }, { _id : 0 } );

Mixing Includes/Excludes

You cannot mix them, with the exception of the _id field. Note also that the $slice operator does not conflict with exclusions on other fields.

Covered Indexes

v1.8+

MongoDB can return data from the index only when the query only involves keys which are present in the index. Not inspecting the actual documents can speed up responses considerably since the index is compact in size and usually fits in RAM, or is sequentially located on disk.

Mongod will automatically use covered index when it can. But be sure that:

  • you provide list of fields to return, so that it can determine that it can be covered by index
  • you must explicitly exclude the _id field by using {_id: 0} (unless the index includes that)
  • as soon as you insert one array value for one of the index keys, the index will immediately become a multikey index and this disables covered index functionality
  • use Explain to determine if the covered index is used: the indexOnly field should be true
// do a login with a covered index, returning the users roles/groups
> db.users.ensureIndex( { username : 1, password : 1, roles : 1} );
> db.users.save({username: "joe", password: "pass", roles: 2})
> db.users.save({username: "liz", password: "pass2", roles: 4})
> db.users.find({username: "joe"}, {_id: 0, roles: 1})
{ "roles" : 2 }
> db.users.find({username: "joe"}, {_id: 0, roles: 1}).explain()
{
	"cursor" : "BtreeCursor username_1_password_1_roles_1",
...
	"indexOnly" : true,
...
}

Dot Notation

You can retrieve partial sub-objects via Dot Notation.

> t.find({})
{ "_id" : ObjectId("4c23f0486dad1c3a68457d20"), "x" : { "y" : 1, "z" : [ 1, 2, 3 ] } }
> t.find({}, {'x.y':1})
{ "_id" : ObjectId("4c23f0486dad1c3
a68457d20"), "x" : { "y" : 1 } }

Retrieving a Subrange of Array Elements

You can use the $slice operator to retrieve a subrange of elements in an array.

db.posts.find({}, {comments:{$slice: 5}}) // first 5 comments
db.posts.find({}, {comments:{$slice: -5}}) // last 5 comments
db.posts.find({}, {comments:{$slice: [20, 10]}}) // skip 20, limit 10
db.posts.find({}, {comments:{$slice: [-20, 10]}}) // 20 from end, limit 10

The examples above will return all fields and only the subset of elements based on the $slice for that field.

Filtering with $slice does not affect other fields inclusion/exclusion. It only applies within the array being sliced.

db.posts.find({}, {_id:1, comments:{$slice: 5}}) // first 5 comments, and the _id field only

See Also


Labels

projection projection Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

PLEASE POST QUESTIONS IN THE FORUMS: http://groups.google.com/group/mongodb-user. Post tips and clarifications here.

blog comments powered by Disqus