$ (projection)

Definition

  • $
  • The positional $ operator limits the contents of an<array> from the query results to contain only the first elementmatching the query document. To specify an array element to update, see thepositional $ operator for updates.

Use $ in the projection document of thefind() method or thefindOne() method when you only need one particulararray element in selected documents.

See the aggregation operator $filter to return anarray with only those elements that match the specified condition.

Usage Considerations

Both the $ operator and the $elemMatch operator projectthe first matching element from an array based on a condition.

The $ operator projects the first matching array element from eachdocument in a collection based on some condition from the query statement.

The $elemMatch projection operator takes an explicit conditionargument. This allows you to project based on a condition not in the query, orif you need to project based on multiple fields in the array’s embedded documents.See Array Field Limitations for an example.

db.collection.find() operations on views do not support $ projection operator.

Behavior

Usage Requirements

Given the form:

  1. db.collection.find( { <array>: <value> ... },
  2. { "<array>.$": 1 } )
  3. db.collection.find( { <array.field>: <value> ...},
  4. { "<array>.$": 1 } )

The <array> field being limited must appear in the query document, and the <value> can be documentsthat contain query operator expressions.

Array Field Limitations

MongoDB requires the following when dealing with projection over arrays:

  • Only one positional $ operator may appear in the projectiondocument.
  • Only one array field, the one being limited with the $projection operator, should appear in the query document. Additional array fields in thequery document may lead to undefined behavior.
  • The query document should onlycontain a single condition on the array field being projected. Multipleconditions may override each other internally and lead to undefinedbehavior.

Under these requirements, the following query is incorrect:

  1. db.collection.find( { <array>: <value>, <someOtherArray>: <value2> },
  2. { "<array>.$": 1 } )

To specify criteria on multiple fields of documents inside that array, use the$elemMatch query operator. The following query returns the firstdocument inside a grades array that has a mean of greater than 70and a grade of greater than 90.

  1. db.students.find( { grades: { $elemMatch: {
  2. mean: { $gt: 70 },
  3. grade: { $gt:90 }
  4. } } },
  5. { "grades.$": 1 } )

You must use the $elemMatch operator if you need separate conditionsfor selecting documents and for choosing fields within those documents.

Sorts and the Positional Operator

When the find() method includes asort(), the find()method applies the sort() to order the matchingdocuments before it applies the positional $projection operator.

If an array field contains multiple documents with the same fieldname and the find() method includes asort() on that repeating field, the returneddocuments may not reflect the sort order because the sort wasapplied to the elements of the array before the $projection operator.

Examples

Project Array Values

A collection students contains the following documents:

  1. { "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] }
  2. { "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] }
  3. { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] }
  4. { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] }
  5. { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] }
  6. { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] }

In the following query, the projection { "grades.$": 1 }returns only the first element greater than or equal to 85for the grades field.

  1. db.students.find( { semester: 1, grades: { $gte: 85 } },
  2. { "grades.$": 1 } )

The operation returns the following documents:

  1. { "_id" : 1, "grades" : [ 87 ] }
  2. { "_id" : 2, "grades" : [ 90 ] }
  3. { "_id" : 3, "grades" : [ 85 ] }

Although the array field grades may contain multiple elementsthat are greater than or equal to 85, the $projection operator returns only the first matching element from thearray.

Project Array Documents

A students collection contains the following documentswhere the grades field is an array of documents; each documentcontain the three field names grade, mean, and std:

  1. { "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 },
  2. { grade: 85, mean: 90, std: 5 },
  3. { grade: 90, mean: 85, std: 3 } ] }
  4.  
  5. { "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 },
  6. { grade: 78, mean: 90, std: 5 },
  7. { grade: 88, mean: 85, std: 3 } ] }

In the following query, the projection { "grades.$": 1 }returns only the first element with the mean greaterthan 70 for the grades field:

  1. db.students.find(
  2. { "grades.mean": { $gt: 70 } },
  3. { "grades.$": 1 }
  4. )

The operation returns the following documents:

  1. { "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] }
  2. { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] }

Further Reading

$elemMatch (projection)