0% found this document useful (0 votes)
4 views237 pages

Query and Projection Operators

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views237 pages

Query and Projection Operators

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Query and Projection Operators

Comparison
Name Description

$eq Matches values that are equal to a specified value.

$gt Matches values that are greater than a specified value.

$gte Matches values that are greater than or equal to a specified value.

$in Matches any of the values specified in an array.

$lt Matches values that are less than a specified value.

$lte Matches values that are less than or equal to a specified value.

$ne Matches all values that are not equal to a specified value.

$nin Matches none of the values specified in an array.

Logical
Name Description

Joins query clauses with a logical AND returns all documents that
$and
match the conditions of both clauses.

Inverts the effect of a query expression and returns documents that


$not
do not match the query expression.

Joins query clauses with a logical NOR returns all documents that fail
$nor
to match both clauses.

Joins query clauses with a logical OR returns all documents that match
$or
the conditions of either clause.
Element
1
Name Description

$exists Matches documents that have the specified field.

$type Selects documents if a field is of the specified type.


Evaluation
Name Description

Allows use of aggregation expressions within the query


$expr
language.

$jsonSchema Validate documents against the given JSON Schema.

Performs a modulo operation on the value of a field and


$mod
selects documents with a specified result.

Selects documents where values match a specified regular


$regex
expression.

$text Performs text search.

$where Matches documents that satisfy a JavaScript expression.


Geospatial
Name Description

Selects geometries that intersect with


$geoIntersects a GeoJSON geometry. The 2dsphere index
supports $geoIntersects.

Selects geometries within a bounding GeoJSON


$geoWithin geometry. The 2dsphere and 2d indexes
support $geoWithin.

$near Returns geospatial objects in proximity to a point.

2
Name Description

Requires a geospatial index.


The 2dsphere and 2d indexes support $near.

Returns geospatial objects in proximity to a point on a


$nearSphere sphere. Requires a geospatial index.
The 2dsphere and 2d indexes support $nearSphere.

Array
Name Description

Matches arrays that contain all elements specified in the


$all
query.

Selects documents if element in the array field matches all the


$elemMatch
specified $elemMatch conditions.

$size Selects documents if the array field is a specified size.


Bitwise
Name Description

Matches numeric or binary values in which a set of bit


$bitsAllClear
positions all have a value of 0.

Matches numeric or binary values in which a set of bit


$bitsAllSet
positions all have a value of 1.

Matches numeric or binary values in which any bit from a


$bitsAnyClear
set of bit positions has a value of 0.

Matches numeric or binary values in which any bit from a


$bitsAnySet
set of bit positions has a value of 1.

Comments
Name Description

3
Name Description

$comment Adds a comment to a query predicate.

Projection Operators¶
Name Description

Projects the first element in an array that matches the query


$
condition.

Projects the first element in an array that matches the


$elemMatch
specified $elemMatch condition.

Projects the document’s score assigned


$meta
during $text operation.

Limits the number of elements projected from an array.


$slice
Supports skip and limit slices.

4
Comparison Query Operators

Name Description

$eq Matches values that are equal to a specified value.

$gt Matches values that are greater than a specified value.

Matches values that are greater than or equal to a specified


$gte
value.

$in Matches any of the values specified in an array.

$lt Matches values that are less than a specified value.

$lte Matches values that are less than or equal to a specified value.

5
Name Description

$ne Matches all values that are not equal to a specified value.

$nin Matches none of the values specified in an array.

6
$eq
$eq

Specifies equality condition. The $eq operator matches


documents where the value of a field equals the specified value.

copy
copied
{ <field>: { $eq: <value> } }

Specifying the $eq operator is equivalent to using the


form { field: <value> } except when the <value> is a regular
expression. See below for examples.

Behavior

Comparison Order

For comparison of different BSON type values, see the specified


BSON comparison order.

Match a Document Value

If the specified <value> is a document, the order of the fields in the


document matters.

Match an Array Value

If the specified <value> is an array, MongoDB matches documents


where the <field> matches the array exactly or the <field> contains
an element that matches the array exactly. The order of the
elements matters. For an example, see Equals an Array Value.

Match a Regular Expression

7
The expression { field: <value> } implicitly specifies a match
on <value>. MongoDB translates the implicit match to a more
explicit form.

When the <value> is fixed, like a particular string, the expression is


equivalent to using the $eq operator { field: { $eq: <value> } }.

If <value> is a regular expression, the statement is expanded using


the $regex operator { field: { $regex: <value> } }.

For examples illustrating this behaviour, see Regex Match


Behaviour.

Security Implications

Always use the explicit form { field: { $eq: <value> } } with user-
supplied input to avoid problems with maliciously formed queries.

Examples

The following examples query against the inventory collection with


the following documents:

copy
copied
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15,
tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20,
tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25,
tags: [ "A", "B" ] }
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30,
tags: [ "B", "A" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20,
tags: [ [ "A", "B" ], "C" ] }

Equals a Specified Value


8
The following example queries the inventory collection to select all
documents where the value of the qty field equals 20:

copy
copied
db.inventory.find( { qty: { $eq: 20 } } )

The query is equivalent to:

copy
copied
db.inventory.find( { qty: 20 } )

Both queries match the following documents:

copy
copied
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20,
tags: [ "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20,
tags: [ [ "A", "B" ], "C" ] }

Field in Embedded Document Equals a Value

The following example queries the inventory collection to select all


documents where the value of the name field in the item document
equals "ab". To specify a condition on a field in an embedded
document, use the dot notation.

copy
copied
db.inventory.find( { "item.name": { $eq: "ab" } } )

The query is equivalent to:

copy
copied

9
db.inventory.find( { "item.name": "ab" } )

Both queries match the following document:

copy
copied
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15,
tags: [ "A", "B", "C" ] }

SEE ALSO
Query Embedded Documents

Array Element Equals a Value

The following example queries the inventory collection to select all


documents where the tags array contains an element with the
value "B" [1]:

copy
copied
db.inventory.find( { tags: { $eq: "B" } } )

The query is equivalent to:

copy
copied
db.inventory.find( { tags: "B" } )

Both queries match the following documents:

copy
copied
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15,
tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20,
tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25,
tags: [ "A", "B" ] }
10
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30,
tags: [ "B", "A" ] }

SEE ALSO
$elemMatch, Query Arrays

The query will also match documents where the value of the tags field
[1]
is the string "B".

Equals an Array Value

The following example queries the inventory collection to select all


documents where the tags array equals exactly the specified array
or the tags array contains an element that equals the
array [ "A", "B" ].

copy
copied
db.inventory.find( { tags: { $eq: [ "A", "B" ] } } )

The query is equivalent to:

copy
copied
db.inventory.find( { tags: [ "A", "B" ] } )

Both queries match the following documents:

copy
copied
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25,
tags: [ "A", "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20,
tags: [ [ "A", "B" ], "C" ] }

11
Regex Match Behaviour

The following examples demonstrate the differences in behavior


between implicit and explict regular expression matching.
Consider a collection with these documents:

copy
copied
{ _id: 001, company: "MongoDB" }
{ _id: 002, company: "MongoDB2" }
$eq match on a string

A string expands to return the same values whether an implicit


match or an explicit use of $eq. Both of these queries:

copy
copied
db.collection.find( { company: "MongoDB" }, {_id: 0
})
db.collection.find( { company: { $eq: "MongoDB" } }
, {_id: 0 } )

return the following result:

{ "company" : "MongoDB" }
$eq match on a regular expression

An explicit query using $eq and a regular expression will only


match an object which is also a regular expresssion. The
example query won’t return anything since values in
the company field are strings.

copy
copied
db.collection.find( { company: { $eq: /MongoDB/ } }
, {_id: 0 } )

12
Regular expression matches

A query with an implicit match against a regular expression is


equivalent to a making a query with the $regex operator. Both of
these queries:

copy
copied
db.collection.find( { company: /MongoDB/ }, {_id: 0
})
db.collection.find( { company: { $regex: /MongoDB/
} }, {_id: 0 } )

return the same results:

{ "company" : "MongoDB" }
{ "company" : "MongoDB2" }

13
$gt
$gt

Syntax: {field: {$gt: value} }

$gt selects those documents where the value of the field is


greater than (i.e. >) the specified value.

For most data types, comparison operators only perform


comparisons on fields where the BSON type matches the query
value’s type. MongoDB supports limited cross-BSON
comparison through Type Bracketing.

Consider the following example:

copy

copied

db.inventory.find( { qty: { $gt: 20 } } )

This query will select all documents in the inventory collection


where the qty field value is greater than 20.

Consider the following example that uses the $gt operator with
a field from an embedded document:

copy

copied

db.inventory.update( { "carrier.fee": { $gt: 2 } },


{ $set: { price: 9.99 } } )

14
This update() operation will set the value of the price field in
the first document found containing the embedded
document carrier whose fee field value is greater than 2.

To set the value of the price field in all documents containing


the embedded document carrier whose fee field value is
greater than 2, specify the multi:true option in
the update() method:

copy

copied

db.inventory.update(
{ "carrier.fee": { $gt: 2 } },
{ $set: { price: 9.99 } },
{ multi: true }
)

15
$gte
$gte

Syntax: {field: {$gte: value} }

$gte selects the documents where the value of the field is


greater than or equal to (i.e. >=) a specified value (e.g. value.)

For most data types, comparison operators only perform


comparisons on fields where the BSON type matches the query
value’s type. MongoDB supports limited cross-BSON
comparison through Type Bracketing.

Consider the following example:

copy

copied

db.inventory.find( { qty: { $gte: 20 } } )

This query would select all documents in inventory where


the qty field value is greater than or equal to 20.

Consider the following example which uses the $gte operator


with a field from an embedded document:

copy

copied

db.inventory.update( { "carrier.fee": { $gte: 2 } }


, { $set: { price: 9.99 } } )

16
This update() operation will set the value of the price field
that contain the embedded document carrier whose fee field
value is greater than or equal to 2.

SEE ALSO
find(), update(), $set.

17
$in
On this page

 Examples
 Use the $in Operator to Match Values
 Use the $in Operator to Match Values in an Array
 Use the $in Operator with a Regular Expression

$in

The $in operator selects the documents where the value of a


field equals any value in the specified array. To specify
an $in expression, use the following prototype:

For comparison of different BSON type values, see the specified


BSON comparison order.

copy
copied
{ field: { $in: [<value1>, <value2>, ... <valueN> ]
} }

If the field holds an array, then the $in operator selects the
documents whose field holds an array that contains at least
one element that matches a value in the specified array (for
example, <value1>, <value2>, and so on).

NOTE
This document describes the $in query operator. For
the $in aggregation operator, see $in (aggregation).

Examples

Use the $in Operator to Match Values

18
Consider the following example:

copy
copied
db.inventory.find( { qty: { $in: [ 5, 15 ] } } )

This query selects all documents in the inventory collection


where the qty field value is either 5 or 15. Although you can
express this query using the $or operator, choose
the $in operator rather than the $or operator when performing
equality checks on the same field.

Use the $in Operator to Match Values in an Array

The collection inventory contains documents that include the


field tags, as in the following:

copy
copied
{ _id: 1, item: "abc", qty: 10, tags: [ "school", "cl
othing" ], sale: false }

Then, the following update() operation will set the sale field
value to true where the tags field holds an array with at least one
element matching either "appliances" or "school".

copy
copied
db.inventory.update(
{ tags: { $in: ["appliances", "s
chool"] } },
{ $set: { sale:true } }
)

For additional examples in querying arrays, see:

 Query an Array

19
 Query an Array of Embedded Documents

For additional examples in querying, see:

 Query Documents

Use the $in Operator with a Regular Expression

The $in operator can specify matching values using regular


expressions of the form /pattern/.
You cannot use $regex operator expressions inside an $in.

Consider the following example:

copy
copied
db.inventory.find( { tags: { $in: [ /^be/, /^st/ ] }
} )

This query selects all documents in the inventory collection


where the tags field holds either a string that starts
with be or st or an array with at least one element that starts
with be or st.

SEE ALSO
find(), update(), $or, $set, $elemMatch.

20
$lt
$lt

Syntax: {field: {$lt: value} }

$lt selects the documents where the value of the field is less
than (i.e. <) the specified value.

For most data types, comparison operators only perform


comparisons on fields where the BSON type matches the query
value’s type. MongoDB supports limited cross-BSON
comparison through Type Bracketing.

Consider the following example:

copy

copied

db.inventory.find( { qty: { $lt: 20 } } )

This query will select all documents in the inventory collection


where the qty field value is less than 20.

Consider the following example which uses the $lt operator


with a field from an embedded document:

copy

copied

db.inventory.update( { "carrier.fee": { $lt: 20 } }


, { $set: { price: 9.99 } } )

21
This update() operation will set the price field value in the
documents that contain the embedded
document carrier whose fee field value is less than 20.

SEE ALSO
find(), update(), $set.
-==============================================

22
$lte
$lte

Syntax: { field: { $lte: value} }

$lte selects the documents where the value of the field is less
than or equal to (i.e. <=) the specified value.

For most data types, comparison operators only perform


comparisons on fields where the BSON type matches the query
value’s type. MongoDB supports limited cross-BSON
comparison through Type Bracketing.

Consider the following example:

copy

copied

db.inventory.find( { qty: { $lte: 20 } } )

This query will select all documents in the inventory collection


where the qty field value is less than or equal to 20.

Consider the following example which uses the $lt operator


with a field from an embedded document:

copy

copied

db.inventory.update( { "carrier.fee": { $lte: 5 } }


, { $set: { price: 9.99 } } )

23
This update() operation will set the price field value in the
documents that contain the embedded
document carrier whose fee field value is less than or equal
to 5.

24
$ne
$ne

Syntax: {field: {$ne: value} }

$ne selects the documents where the value of the field is not
equal to the specified value. This includes documents that do
not contain the field.

For comparison of different BSON type values, see the specified


BSON comparison order.

Consider the following example:

copy

copied

db.inventory.find( { qty: { $ne: 20 } } )

This query will select all documents in the inventory collection


where the qty field value does not equal 20, including those
documents that do not contain the qty field.

Consider the following example which uses the $ne operator


with a field in an embedded document:

copy

copied

db.inventory.update( { "carrier.state": { $ne: "NY"


} }, { $set: { qty: 20 } } )

25
This update() operation will set the qty field value in the
documents that contain the embedded
document carrier whose state field value does not equal
“NY”, or where the state field or the carrier embedded
document do not exist.

The inequality operator $ne is not very selective since it often


matches a large portion of the index. As a result, in many cases,
a $ne query with an index may perform no better than
a $ne query that must scan all documents in a collection. See
also Query Selectivity.

26
$nin
$nin

Syntax: { field: { $nin: [ <value1>, <value2> ... <v


alueN> ]} }

$nin selects the documents where:

 the field value is not in the specified array or


 the field does not exist.

For comparison of different BSON type values, see the specified


BSON comparison order.

Consider the following query:

copy
copied
db.inventory.find( { qty: { $nin: [ 5, 15 ] } } )

This query will select all documents in the inventory collection


where the qty field value does not equal 5 nor 15. The selected
documents will include those documents that do not contain
the qty field.

If the field holds an array, then the $nin operator selects the
documents whose field holds an array with no element equal
to a value in the specified array (e.g. <value1>, <value2>, etc.).

27
Consider the following query:

copy
copied
db.inventory.update( { tags: { $nin: [ "appliances"
, "school" ] } }, { $set: { sale: false } } )

This update() operation will set the sale field value in


the inventory collection where the tags field holds an array
with no elements matching an element in the
array ["appliances", "school"] or where a document does
not contain the tags field.

The inequality operator $nin is not very selective since it often


matches a large portion of the index. As a result, in many cases,
a $nin query with an index may perform no better than
a $nin query that must scan all documents in a collection. See
also Query Selectivity.

SEE ALSO
find(), update(), $set.

28
Logical Query Operators
NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

Joins query clauses with a logical AND returns all documents


$and
that match the conditions of both clauses.

Inverts the effect of a query expression and returns documents


$not
that do not match the query expression.

Joins query clauses with a logical NOR returns all documents


$nor
that fail to match both clauses.

Joins query clauses with a logical OR returns all documents


$or
that match the conditions of either clause.

29
$and
On this page

 Examples

$and

Syntax: { $and: [ { <expression1> }, { <expression2>


} , ... , { <expressionN> } ] }

$and performs a logical AND operation on an array of one or


more expressions (e.g. <expression1>, <expression2>, etc.) and
selects the documents that satisfy all the expressions in the array.
The $and operator uses short-circuit evaluation. If the first expression
(e.g. <expression1>) evaluates to false, MongoDB will not evaluate
the remaining expressions.

NOTE
MongoDB provides an implicit AND operation when specifying a comma
separated list of expressions.

Examples

AND Queries With Multiple Expressions Specifying the Same Field

Consider the following example:

copy
copied
db.inventory.find( { $and: [ { price: { $ne: 1.99 } }
, { price: { $exists: true } } ] } )

This query will select all documents in the inventory collection where:

30
 the price field value is not equal to 1.99 and
 the price field exists.

This query can be also be constructed with an implicit AND operation by


combining the operator expressions for the price field. For example, this
query can be written as:

copy
copied
db.inventory.find( { price: { $ne: 1.99, $exists: tru
e } } )

AND Queries With Multiple Expressions Specifying the Same


Operator

Consider the following example:

copy
copied
db.inventory.find( {
$and: [
{ $or: [ { qty: { $lt : 10 } }, { qty : { $gt
: 50 } } ] },
{ $or: [ { sale: true }, { price : { $lt : 5
} } ] }
]
} )

This query will select all documents where:

 the qty field value is less than 10 or greater than 50, and
 the sale field value is equal to true or the price field value
is less than 5.

This query cannot be constructed using an implicit AND operation,


because it uses the $or operator more than once.

31
$not
On this page

 Behavior

$not

Syntax: { field: { $not: { <operator-


expression> } } }

$not performs a logical NOT operation on the specified <operator-


expression> and selects the documents that do not match
the <operator-expression>. This includes documents that do not
contain the field.

Consider the following query:

copy
copied
db.inventory.find( { price: { $not: { $gt: 1.99 } }
} )

This query will select all documents in the inventory collection


where:

 the price field value is less than or equal to 1.99 or


 the price field does not exist

{ $not: { $gt: 1.99 } } is different from


the $lte operator. { $lte: 1.99 } returns only the documents
where price field exists and its value is less than or equal to 1.99.

Remember that the $not operator only affects other operators and
cannot check fields and documents independently. So, use

32
the $not operator for logical disjunctions and the $ne operator to test
the contents of fields directly.

Behavior

$not and Data Types

The operation of the $not operator is consistent with the behavior of


other operators but may yield unexpected results with some data types
like arrays.

$not and Regular Expressions

$not operator can perform logical NOT operation on:

 regular expression objects (i.e. /pattern/)


For example, the following query selects all documents in
the inventory collection where the item field value
does not start with the letter p.

copy

copied

db.inventory.find( { item: { $not: /^p.*/ } } )


 $regex operator expression (Starting in MongoDB 4.0.7)
For example, the following query selects all documents in
the inventory collection where the item field value
does not start with the letter p.

copy

copied

db.inventory.find( { item: { $not: { $regex: "^p


.*" } } } )
db.inventory.find( { item: { $not: { $regex: /^p
.*/ } } } )
33
 driver language’s regular expression objects
For example, the following PyMongo query uses
Python’s re.compile() method to compile a regular
expression:

copy

copied

import re
for noMatch in db.inventory.find( { "item": { "$
not": re.compile("^p.*") } } ):
print noMatch

34
$nor
On this page

 Examples

$nor

$nor performs a logical NOR operation on an array of one or


more query expression and selects the documents that fail all
the query expressions in the array. The $nor has the following
syntax:

copy
copied
{ $nor: [ { <expression1> }, { <expression2> }, ...
{ <expressionN> } ] }

SEE ALSO
find(), update(), $or, $set, and $exists.

Examples

$nor Query with Two Expressions

Consider the following query which uses only the $nor operator:

copy
copied
db.inventory.find( { $nor: [ { price: 1.99 }, { sale:
true } ] } )

This query will return all documents that:

35
 contain the price field whose value is not equal to 1.99 and
contain the sale field whose value is not equal to true or
 contain the price field whose value is not equal
to 1.99 but do not contain the sale field or
 do not contain the price field but contain the sale field
whose value is not equal to true or
 do not contain the price field and do not contain
the sale field

$nor and Additional Comparisons

Consider the following query:

copy
copied
db.inventory.find( { $nor: [ { price: 1.99 }, { qty:
{ $lt: 20 } }, { sale: true } ] } )

This query will select all documents in the inventory collection


where:

 the price field value does not equal 1.99 and


 the qty field value is not less than 20 and
 the sale field value is not equal to true

including those documents that do not contain these field(s).

The exception in returning documents that do not contain the field


in the $nor expression is when the $nor operator is used with
the $exists operator.

$nor and $exists

Compare that with the following query which uses


the $nor operator with the $exists operator:

copy

36
copied
db.inventory.find( { $nor: [ { price: 1.99 }, { price
: { $exists: false } },
{ sale: true }, { sale:
{ $exists: false } } ] } )

This query will return all documents that:

 contain the price field whose value is not equal to 1.99 and
contain the sale field whose value is not equal to true

37
$or
On this page

 Behaviors

$or

The $or operator performs a logical OR operation on an array


of two or more <expressions> and selects the documents that
satisfy at least one of the <expressions>. The $or has the
following syntax:

copy
copied
{ $or: [ { <expression1> }, { <expression2> }, ...
, { <expressionN> } ] }

Consider the following example:

copy
copied
db.inventory.find( { $or: [ { quantity: { $lt: 20 }
}, { price: 10 } ] } )

This query will select all documents in the inventory collection


where either the quantity field value is less
than 20 or the price field value equals 10.

Behaviors

$or Clauses and Indexes

When evaluating the clauses in the $or expression, MongoDB


either performs a collection scan or, if all the clauses are

38
supported by indexes, MongoDB performs index scans. That is,
for MongoDB to use indexes to evaluate an $or expression, all the
clauses in the $or expression must be supported by indexes.
Otherwise, MongoDB will perform a collection scan.

When using indexes with $or queries, each clause of an $or can
use its own index. Consider the following query:

copy
copied
db.inventory.find( { $or: [ { quantity: { $lt: 20 } }
, { price: 10 } ] } )

To support this query, rather than a compound index, you would


create one index on quantity and another index on price:

copy
copied
db.inventory.createIndex( { quantity: 1 } )
db.inventory.createIndex( { price: 1 } )

MongoDB can use all but the geoHaystack index to


support $or clauses.

$or and text Queries

If $or includes a $text query, all clauses in the $or array must be
supported by an index. This is because a $text query must use
an index, and $or can only use indexes if all its clauses are
supported by indexes. If the $text query cannot use an index, the
query will return an error.

$or and GeoSpatial Queries

$or supports geospatial clauses with the following exception for


the near clause (near clause

39
includes $nearSphere and $near). $or cannot contain a near
clause with any other clause.

$or and Sort Operations

When executing $or queries with a sort(), MongoDB can now


use indexes that support the $or clauses. Previous versions did
not use the indexes.

$or versus $in

When using $or with <expressions> that are equality checks for
the value of the same field, use the $in operator instead of
the $or operator.

For example, to select all documents in the inventory collection


where the quantity field value equals either 20 or 50, use
the $in operator:

copy
copied
db.inventory.find ( { quantity: { $in: [20, 50] } } )

Nested $or Clauses

You may nest $or operations.

40
Element Query Operators
NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

$exists Matches documents that have the specified field.

$type Selects documents if a field is of the specified type.

41
$exists
On this page

 Definition
 Examples

Definition

$exists

Syntax: { field: { $exists: <boolean> } }

When <boolean> is true, $exists matches the documents that


contain the field, including documents where the field value is null.
If <boolean> is false, the query returns only the documents that do
not contain the field. [1]

MongoDB $exists does not correspond to SQL operator exists. For


SQL exists, refer to the $in operator.

SEE ALSO
$nin, $in, and Query for Null or Missing Fields.

Starting in MongoDB 4.2, users can no longer use the query


[1] filter $type: 0 as a synonym for $exists:false. To query for null
or missing fields, see Query for Null or Missing Fields.

Examples

Exists and Not Equal To

42
Consider the following example:

copy

copied

db.inventory.find( { qty: { $exists: true, $nin: [ 5,


15 ] } } )

This query will select all documents in the inventory collection where
the qty field exists and its value does not equal 5 or 15.

Null Values

The following examples uses a collection named records with the


following documents:

copy

copied

{ a: 5, b: 5, c: null }
{ a: 3, b: null, c: 8 }
{ a: null, b: 3, c: 9 }
{ a: 1, b: 2, c: 3 }
{ a: 2, c: 5 }
{ a: 3, b: 2 }
{ a: 4 }
{ b: 2, c: 4 }
{ b: 2 }
{ c: 6 }

$exists: true

The following query specifies the query


predicate a: { $exists: true }:

43
copy

copied

db.records.find( { a: { $exists: true } } )

The results consist of those documents that contain the field a, including
the document whose field a contains a null value:

copy

copied

{ a: 5, b: 5, c: null }
{ a: 3, b: null, c: 8 }
{ a: null, b: 3, c: 9 }
{ a: 1, b: 2, c: 3 }
{ a: 2, c: 5 }
{ a: 3, b: 2 }
{ a: 4 }

$exists: false

The following query specifies the query


predicate b: { $exists: false }:

copy

copied

db.records.find( { b: { $exists: false } } )

The results consist of those documents that do not contain the


field b:

copy

copied

44
{ a: 2, c: 5 }
{ a: 4 }
{ c: 6 }

Starting in MongoDB 4.2, users can no longer use the query


filter $type: 0 as a synonym for $exists:false. To query for
null or missing fields, see Query for Null or Missing Fields.

45
$type
On this page

 Definition
 Behavior
 Examples
 Querying by Array Type
 Additional Information

Definition

$type

$type selects documents where the value of the field is an


instance of the specified BSON type(s). Querying by data type is
useful when dealing with highly unstructured data where data
types are not predictable.

A $type expression for a single BSON type has the following


syntax:

Changed in version 3.2.

copy
copied
{ field: { $type: <BSON type> } }

You can specify either the number or alias for the BSON type

The $type expression can also accept an array of BSON types


and has the following syntax:

copy
copied

46
{ field: { $type: [ <BSON type1> , <BSON type2>, ..
. ] } }

The above query will match documents where the field value is
any of the listed types. The types specified in the array can be
either numeric or string aliases.

See Querying by Multiple Data Type for an example.

Available Types describes the BSON types and their


corresponding numeric and string aliases.

SEE ALSO

 $isNumber - checks if the argument is a number. New in


MongoDB 4.4
 $type (Aggregation) - returns the BSON type of the
argument.

Behavior

$type returns documents where the BSON type of


the field matches the BSON type passed to $type.

Arrays

For documents where field is an array, $type returns


documents in which at least one array element matches a type
passed to $type.

Querying for the Array BSON Type

With MongoDB 3.6 and later, querying


for $type: "array" returns documents where the field itself is an
array. Prior to MongoDB 3.6, $type: "array" returned
documents where the field is an array containing at least one

47
element of type array. For example, given the following
documents:

copy
copied
{ "data" : [ "values", [ "values" ] ] }
{ "data" : [ "values" ] }

With MongoDB 3.6 and later, the


query find( {"data" : { $type : "array" } } ) returns
both documents. Prior to MongoDB 3.6, the query returns only the
first document.

Available Types

Starting in MongoDB 3.2, $type operator accepts string aliases for


the BSON types in addition to the numbers corresponding to the
BSON types. Previous versions only accepted the numbers
corresponding to the BSON type. [1]

Type Number Alias Notes

Double 1 “double”

String 2 “string”

Object 3 “object”

48
Type Number Alias Notes

Array 4 “array”

Binary data 5 “binData”

Undefined 6 “undefined” Deprecated.

ObjectId 7 “objectId”

Boolean 8 “bool”

Date 9 “date”

Null 10 “null”

11 “regex”
Regular

49
Type Number Alias Notes

Expression

DBPointer 12 “dbPointer” Deprecated.

JavaScript 13 “javascript”

Symbol 14 “symbol” Deprecated.

JavaScript code Deprecated in


15 “javascriptWithScope”
with scope MongoDB 4.4.

32-bit integer 16 “int”

Timestamp 17 “timestamp”

64-bit integer 18 “long”

50
Type Number Alias Notes

Decimal128 19 “decimal” New in version 3.4.

Min key -1 “minKey”

Max key 127 “maxKey”

$type supports the number alias, which will match against the
following BSON types:

 double
 32-bit integer
 64-bit integer
 decimal

For examples, see Examples.

Starting in MongoDB 4.2, users can no longer use the query


[1] filter $type: 0 as a synonym for $exists:false. To query for
null or missing fields, see Query for Null or Missing Fields.

SEE ALSO
$isNumber New in MongoDB 4.4

MinKey and MaxKey

51
MinKey and MaxKey are used in comparison operations and exist
primarily for internal use. For all possible BSON element
values, MinKey will always be the smallest value while MaxKey will
always be the greatest value.

Querying for minKey or maxKey with $type will only return fields
that match the special MinKey or MaxKey values.

Suppose that the data collection has two documents


with MinKey and MaxKey:

copy
copied
{ "_id" : 1, x : { "$minKey" : 1 } }
{ "_id" : 2, y : { "$maxKey" : 1 } }

The following query will return the document with _id: 1:

copy
copied
db.data.find( { x: { $type: "minKey" } } )

The following query will return the document with _id: 2:

copy
copied
db.data.find( { y: { $type: "maxKey" } } )

Examples

Querying by Data Type

The addressBook contains addresses and zipcodes,


where zipCode has string, int, double, and long values:

copy
copied

52
db.addressBook.insertMany(
[
{ "_id" : 1, address : "2030 Martian Way", zipC
ode : "90698345" },
{ "_id" : 2, address: "156 Lunar Place", zipCod
e : 43339374 },
{ "_id" : 3, address : "2324 Pluto Place", zipC
ode: NumberLong(3921412) },
{ "_id" : 4, address : "55 Saturn Ring" , zipCo
de : NumberInt(88602117) },
{ "_id" : 5, address : "104 Venus Drive", zipCo
de : ["834847278", "1893289032"]}
]
)

The following queries return all documents where zipCode is


the BSON type string or is an array containing an element of the
specified type:

copy
copied
db.addressBook.find( { "zipCode" : { $type : 2 } } );
db.addressBook.find( { "zipCode" : { $type : "string"
} } );

These queries return:

copy
copied
{ "_id" : 1, "address" : "2030 Martian Way", "zipCode
" : "90698345" }
{ "_id" : 5, "address" : "104 Venus Drive", "zipCode"
: [ "834847278", "1893289032" ] }

53
The following queries return all documents where zipCode is
the BSON type double or is an array containing an element of the
specified type:

copy
copied
db.addressBook.find( { "zipCode" : { $type : 1 } } )
db.addressBook.find( { "zipCode" : { $type : "double"
} } )

These queries return:

copy
copied
{ "_id" : 2, "address" : "156 Lunar Place", "zipCode"
: 43339374 }

The following query uses the number alias to return documents


where zipCode is the BSON type double, int, or long or is an
array containing an element of the specified types:

copy
copied
db.addressBook.find( { "zipCode" : { $type : "number"
} } )

These queries return:

copy
copied
{ "_id" : 2, "address" : "156 Lunar Place", "zipCode"
: 43339374 }
{ "_id" : 3, "address" : "2324 Pluto Place", "zipCode
" : NumberLong(3921412) }
{ "_id" : 4, "address" : "55 Saturn Ring", "zipCode"
: 88602117 }

54
Querying by Multiple Data Type

The grades collection contains names and averages,


where classAverage has string, int, and double values:

copy
copied
db.grades.insertMany(
[
{ "_id" : 1, name : "Alice King" , classAverage
: 87.333333333333333 },
{ "_id" : 2, name : "Bob Jenkins", classAverage
: "83.52" },
{ "_id" : 3, name : "Cathy Hart", classAverage:
"94.06" },
{ "_id" : 4, name : "Drew Williams" , classAver
age : NumberInt("93") }
]
)

The following queries return all documents


where classAverage is the BSON type string or double or is an
array containing an element of the specified types. The first query
uses numeric aliases while the second query uses string aliases.

copy
copied
db.grades.find( { "classAverage" : { $type : [ 2 , 1
] } } );
db.grades.find( { "classAverage" : { $type : [ "strin
g" , "double" ] } } );

These queries return the following documents:

copy
copied

55
{ "_id" : 1, "name" : "Alice King", "classAverage" :
87.33333333333333 }
{ "_id" : 2, "name" : "Bob Jenkins", "classAverage" :
"83.52" }
{ "_id" : 3, "name" : "Cathy Hart", "classAverage" :
"94.06" }

Querying by MinKey and MaxKey

The restaurants collection uses minKey for any grade that is a


failing grade:

copy
copied
{
"_id": 1,
"address": {
"building": "230",
"coord": [ -73.996089, 40.675018 ],
"street": "Huntington St",
"zipcode": "11231"
},
"borough": "Brooklyn",
"cuisine": "Bakery",
"grades": [
{ "date": new Date(1393804800000), "grade": "C"
, "score": 15 },
{ "date": new Date(1378857600000), "grade": "C"
, "score": 16 },
{ "date": new Date(1358985600000), "grade": Min
Key(), "score": 30 },
{ "date": new Date(1322006400000), "grade": "C"
, "score": 15 }
],
"name": "Dirty Dan's Donuts",
"restaurant_id": "30075445"

56
}

And maxKey for any grade that is the highest passing grade:

copy
copied
{
"_id": 2,
"address": {
"building": "1166",
"coord": [ -73.955184, 40.738589 ],
"street": "Manhattan Ave",
"zipcode": "11222"
},
"borough": "Brooklyn",
"cuisine": "Bakery",
"grades": [
{ "date": new Date(1393804800000), "grade": Max
Key(), "score": 2 },
{ "date": new Date(1378857600000), "grade": "B"
, "score": 6 },
{ "date": new Date(1358985600000), "grade": Max
Key(), "score": 3 },
{ "date": new Date(1322006400000), "grade": "B"
, "score": 5 }
],
"name": "Dainty Daisey's Donuts",
"restaurant_id": "30075449"
}

The following query returns any restaurant


whose grades.grade field contains minKey or is an array
containing an element of the specified type:

copy
copied

57
db.restaurants.find(
{ "grades.grade" : { $type : "minKey" } }
)

This returns

copy
copied
{
"_id" : 1,
"address" : {
"building" : "230",
"coord" : [ -73.996089, 40.675018 ],
"street" : "Huntington St",
"zipcode" : "11231"
},
"borough" : "Brooklyn",
"cuisine" : "Bakery",
"grades" : [
{ "date" : ISODate("2014-03-03T00:00:00Z"), "gr
ade" : "C", "score" : 15 },
{ "date" : ISODate("2013-09-11T00:00:00Z"), "gr
ade" : "C", "score" : 16 },
{ "date" : ISODate("2013-01-24T00:00:00Z"), "gr
ade" : { "$minKey" : 1 }, "score" : 30 },
{ "date" : ISODate("2011-11-23T00:00:00Z"), "gr
ade" : "C", "score" : 15 }
],
"name" : "Dirty Dan's Donuts",
"restaurant_id" : "30075445"
}

The following query returns any restaurant


whose grades.grade field contains maxKey or is an array
containing an element of the specified type:

58
copy
copied
db.restaurants.find(
{ "grades.grade" : { $type : "maxKey" } }
)

This returns

copy
copied
{
"_id" : 2,
"address" : {
"building" : "1166",
"coord" : [ -73.955184, 40.738589 ],
"street" : "Manhattan Ave",
"zipcode" : "11222"
},
"borough" : "Brooklyn",
"cuisine" : "Bakery",
"grades" : [
{ "date" : ISODate("2014-03-03T00:00:00Z"), "gr
ade" : { "$maxKey" : 1 }, "score" : 2 },
{ "date" : ISODate("2013-09-11T00:00:00Z"), "gr
ade" : "B", "score" : 6 },
{ "date" : ISODate("2013-01-24T00:00:00Z"), "gr
ade" : { "$maxKey" : 1 }, "score" : 3 },
{ "date" : ISODate("2011-11-23T00:00:00Z"), "gr
ade" : "B", "score" : 5 }
],
"name" : "Dainty Daisey's Donuts",
"restaurant_id" : "30075449"
}

Querying by Array Type

59
A collection named SensorReading contains the following
documents:

copy
copied
{
"_id": 1,
"readings": [
25,
23,
[ "Warn: High Temp!", 55 ],
[ "ERROR: SYSTEM SHUTDOWN!", 66 ]
]
},
{
"_id": 2,
"readings": [
25,
25,
24,
23
]
},
{
"_id": 3,
"readings": [
22,
24,
[]
]
},
{
"_id": 4,
"readings": []
},
{

60
"_id": 5,
"readings": 24
}

The following query returns any document in which


the readings field is an array, empty or non-empty.

copy
copied
db.SensorReading.find( { "readings" : { $type: "array
" } } )

The above query returns the following documents:

copy
copied
{
"_id": 1,
"readings": [
25,
23,
[ "Warn: High Temp!", 55 ],
[ "ERROR: SYSTEM SHUTDOWN!", 66 ]
]
},
{
"_id": 2,
"readings": [
25,
25,
24,
23
]
},
{
"_id": 3,

61
"readings": [
22,
24,
[]
]
},
{
"_id": 4,
"readings": []
}

In the documents with _id : 1, _id : 2, _id : 3, and _id : 4,


the readings field is an array.

Additional Information

 Query for Null or Missing Fields


 db.collection.find()
 BSON Types.

62
Evaluation Query Operators
NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

Allows use of aggregation expressions within the


$expr
query language.

$jsonSchema Validate documents against the given JSON Schema.

Performs a modulo operation on the value of a field


$mod
and selects documents with a specified result.

Selects documents where values match a specified


$regex
regular expression.

$text Performs text search.

63
Name Description

Matches documents that satisfy a JavaScript


$where
expression.

64
$expr
On this page

 Definition
 Behavior
 Examples

Definition

New in version 3.6.

$expr

Allows the use of aggregation expressions within the query


language.

$expr has the following syntax:

copy
copied
{ $expr: { <expression> } }

The arguments can be any valid aggregation expression. For


more information, see Expressions.

Behavior

 $expr can build query expressions that compare fields from the
same document in a $match stage.
o If the $match stage is part of a $lookup stage, $expr can
compare fields using let variables. See Specify Multiple Join
Conditions with $lookup for an example.
o $expr only uses indexes on the from collection for equality
matches in a $match stage.

65
 $expr does not support multikey indexes.

Examples

Compare Two Fields from A Single Document

Consider an monthlyBudget collection with the following


documents:

copy
copied
{ "_id" : 1, "category" : "food", "budget": 400, "spe
nt": 450 }
{ "_id" : 2, "category" : "drinks", "budget": 100, "s
pent": 150 }
{ "_id" : 3, "category" : "clothes", "budget": 100, "
spent": 50 }
{ "_id" : 4, "category" : "misc", "budget": 500, "spe
nt": 300 }
{ "_id" : 5, "category" : "travel", "budget": 200, "s
pent": 650 }

The following operation uses $expr to find documents where


the spent amount exceeds the budget:

copy
copied
db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "
$budget" ] } } )

The operation returns the following results:

copy
copied
{ "_id" : 1, "category" : "food", "budget" : 400, "sp
ent" : 450 }

66
{ "_id" : 2, "category" : "drinks", "budget" : 100, "
spent" : 150 }
{ "_id" : 5, "category" : "travel", "budget" : 200, "
spent" : 650 }

Using $expr With Conditional Statements

Some queries require the ability to execute conditional logic when


defining a query filter. The aggregation framework provides
the $cond operator to express conditional statements. By
using $expr with the $cond operator, you can specify a
conditional filter for your query statement.

Create a sample supplies collection with the following


documents:

copy
copied
db.supplies.insertMany([
{ "_id" : 1, "item" : "binder", "qty" : NumberInt(
"100"), "price" : NumberDecimal("12") },
{ "_id" : 2, "item" : "notebook", "qty" : NumberIn
t("200"), "price" : NumberDecimal("8") },
{ "_id" : 3, "item" : "pencil", "qty" : NumberInt(
"50"), "price" : NumberDecimal("6") },
{ "_id" : 4, "item" : "eraser", "qty" : NumberInt(
"150"), "price" : NumberDecimal("3") },
{ "_id" : 5, "item" : "legal pad", "qty" : NumberI
nt("42"), "price" : NumberDecimal("10") }
])

Assume that for an upcoming sale next month, you want to


discount the prices such that:

 If qty is greater than or equal to 100, the discounted price


will be 0.5 of the price.

67
 If qty is less than 100, the discounted price is 0.75 of
the price.

Before applying the discounts, you would like to know which


items in the supplies collection have a discounted price of less
than 5.

The following example uses $expr with $cond to calculate the


discounted price based on the qty and $lt to return documents
whose calculated discount price is less
than NumberDecimal("5"):

copy
copied
// Aggregation expression to calculate discounted pri
ce

let discountedPrice = {
$cond: {
if: { $gte: ["$qty", 100] },
then: { $multiply: ["$price", NumberDecimal("0.
50")] },
else: { $multiply: ["$price", NumberDecimal("0.
75")] }
}
};

// Query the supplies collection using the aggregatio


n expression

db.supplies.find( { $expr: { $lt:[ discountedPrice,


NumberDecimal("5") ] } });

The following table shows the discounted price for each document
and whether discounted price is less
than NumberDecimal("5") (i.e. whether the document meets the
query condition).
68
<
Document Discounted Price
NumberDecimal(“5”)

{“_id”: 1, “item”:
“binder”, “qty”: 100,
NumberDecimal(“6.00”) false
“price”:
NumberDecimal(“12”) }

{“_id”: 2, “item”:
“noteboook”, “qty”: 200,
NumberDecimal(“4.00”) true
“price”:
NumberDecimal(“8”) }

{“_id”: 3, “item”:
“pencil”, “qty”: 50,
NumberDecimal(“4.50”) true
“price”:
NumberDecimal(“6”) }

{“_id”: 4, “item”:
“eraser”, “qty”: 150,
NumberDecimal(“1.50”) true
“price”:
NumberDecimal(“3”) }

69
<
Document Discounted Price
NumberDecimal(“5”)

{“_id”: 5, “item”: “legal


pad”, “qty”: 42, “price”: NumberDecimal(“7.50”) false
NumberDecimal(“10”) }

The db.collection.find() operation returns the documents


whose calculated discount price is less
than NumberDecimal("5"):

copy
copied
{ "_id" : 2, "item" : "notebook", "qty": 200 , "price
": NumberDecimal("8") }
{ "_id" : 3, "item" : "pencil", "qty": 50 , "price":
NumberDecimal("6") }
{ "_id" : 4, "item" : "eraser", "qty": 150 , "price":
NumberDecimal("3") }

Even though $cond calculates an effective discounted price, that


price is not reflected in the returned documents. Instead, the
returned documents represent the matching documents in their
original state. The find operation did not return
the binder or legal pad documents, as their discounted price
was greater than 5.

70
$jsonSchema
On this page

 Definition
 Behavior
 Examples
 JSON Schema

Definition

$jsonSchema

New in version 3.6.

The $jsonSchema operator matches documents that satisfy the


specified JSON Schema.

The $jsonSchema operator expression has the following syntax:

copy
copied
{ $jsonSchema: <JSON Schema object> }

Where the JSON Schema object is formatted according to draft 4


of the JSON Schema standard.

copy
copied
{ <keyword1>: <value1>, ... }

For example:

copy
copied

71
{
$jsonSchema: {
required: [ "name", "major", "gpa", "address"
],
properties: {
name: {
bsonType: "string",
description: "must be a string and is re
quired"
},
address: {
bsonType: "object",
required: [ "zipcode" ],
properties: {
"street": { bsonType: "string" },
"zipcode": { bsonType: "string" }
}
}
}
}
}

For a list of keywords supported by MongoDB, see Available


Keywords.

NOTE
MongoDB supports draft 4 of JSON Schema, including core
specification and validation specification, with some differences.
See Extensions and Omissions for details.
For more information about JSON Schema, see the official
website.

Behavior

Feature Compatibility

72
The featureCompatibilityVersion must be set to "3.6" or higher in
order to use $jsonSchema.

Document Validator

You can use $jsonSchema in a document validator to enforce the


specified schema on insert and update operations:

copy
copied
db.createCollection( <collection>, { validator: { $js
onSchema: <schema> } } )
db.runCommand( { collMod: <collection>, validator:{ $
jsonSchema: <schema> } } )

Query Conditions

You can use $jsonSchema in query conditions for read and write
operations to find documents in the collection that satisfy the
specified schema:

db.collection.find( { $jsonSchema: <schema> } )


db.collection.aggregate( [ { $match: { $jsonSchema: <
schema> } } ] )
db.collection.updateMany( { $jsonSchema: <schema> },
<update> )
db.collection.deleteOne( { $jsonSchema: <schema> } )

To find documents in the collection that do not satisfy the


specified schema, use the $jsonSchema expression in
a $nor expression. For example:

db.collection.find( { $nor: [ { $jsonSchema: <schema>


} ] } )
db.collection.aggregate( [ { $match: { $nor: [ { $jso
nSchema: <schema> } ] } }, ... ] )

73
db.collection.updateMany( { $nor: [ { $jsonSchema: <s
chema> } ] }, <update> )
db.collection.deleteOne( { $nor: [ { $jsonSchema: <sc
hema> } ] } )

Examples

Schema Validation

The following db.createCollection() method creates a


collection named students and uses the $jsonSchema operator
to set schema validation rules:

copy
copied
db.createCollection("students", {
validator: {
$jsonSchema: {
bsonType: "object",
required: [ "name", "year", "major", "addres
s" ],
properties: {
name: {
bsonType: "string",
description: "must be a string and is
required"
},
year: {
bsonType: "int",
minimum: 2017,
maximum: 3017,
description: "must be an integer in [
2017, 3017 ] and is required"
},
major: {

74
enum: [ "Math", "English", "Computer S
cience", "History", null ],
description: "can only be one of the e
num values and is required"
},
gpa: {
bsonType: [ "double" ],
description: "must be a double if the
field exists"
},
address: {
bsonType: "object",
required: [ "city" ],
properties: {
street: {
bsonType: "string",
description: "must be a string i
f the field exists"
},
city: {
bsonType: "string",
"description": "must be a string
and is required"
}
}
}
}
}
}
})

Given the created validator for the collection, the following


insert operation will fail because gpa is an integer when
the validator requires a double.

copy
75
copied
db.students.insert({
name: "Alice",
year: NumberInt(2019),
major: "History",
gpa: NumberInt(3),
address: {
city: "NYC",
street: "33rd Street"
}
})

The operation returns the following error:

WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})

After changing the gpa to a double, the insert succeeds:

copy
copied
db.students.insert({
name: "Alice",
year: NumberInt(2019),
major: "History",
gpa: 3.0,
address: {
city: "NYC",
street: "33rd Street"
}
})

76
The operation returns the following:

WriteResult({ "nInserted" : 1 })

Query Conditions

You can use $jsonSchema in query conditions for read and write
operations to find documents in the collection that satisfy the
specified schema.

For example, create a sample collection inventory with the


following documents:

copy
copied
db.inventory.insertMany([
{ item: "journal", qty: NumberInt(25), size: { h:
14, w: 21, uom: "cm" }, instock: true },
{ item: "notebook", qty: NumberInt(50), size: { h:
8.5, w: 11, uom: "in" }, instock: true },
{ item: "paper", qty: NumberInt(100), size: { h: 8
.5, w: 11, uom: "in" }, instock: 1 },
{ item: "planner", qty: NumberInt(75), size: { h:
22.85, w: 30, uom: "cm" }, instock: 1 },
{ item: "postcard", qty: NumberInt(45), size: { h:
10, w: 15.25, uom: "cm" }, instock: true },
{ item: "apple", qty: NumberInt(45), status: "A",
instock: true },
{ item: "pears", qty: NumberInt(50), status: "A",
instock: true }
])

Next, define the following sample schema object:

copy
copied
let myschema = {
77
required: [ "item", "qty", "instock" ],
properties: {
item: { bsonType: "string" },
qty: { bsonType: "int" },
size: {
bsonType: "object",
required: [ "uom" ],
properties: {
uom: { bsonType: "string" },
h: { bsonType: "double" },
w: { bsonType: "double" }
}
},
instock: { bsonType: "bool" }
}
}

You can use $jsonSchema to find all documents in the collection


that satisfy the schema:

copy
copied
db.inventory.find( { $jsonSchema: myschema } )
db.inventory.aggregate( [ { $match: { $jsonSchema: my
schema } } ] )

You can use $jsonSchema with the $nor to find all documents
that do not satisfy the schema:

copy
copied
db.inventory.find( { $nor: [ { $jsonSchema: myschema
} ] } )

Or, you can update all documents that do not satisfy the schema:

78
copy
copied
db.inventory.updateMany( { $nor: [ { $jsonSchema: mys
chema } ] }, { $set: { isValid: false } } )

Or, you can delete all documents that do not satisfy the schema:

copy
copied
db.inventory.deleteMany( { $nor: [ { $jsonSchema: mys
chema } ] } )

JSON Schema

MongoDB supports draft 4 of JSON Schema, including core


specification and validation specification, with some differences.
See Extensions and Omissions for details.

For more information about JSON Schema, see the official


website.

Available Keywords

NOTE
MongoDB implements a subset of keywords available in JSON
Schema. For a complete list of omissions, see Omissions.

Keyword Type Definition Behavior

string Accepts same string


bsonType all types alias or aliases used for
array of the $type operator
string

79
Keyword Type Definition Behavior

aliases

array of Enumerates all possible values


enum all types
values of the field

Enumerates the possible JSON


types of the field. Available
types are “object”, “array”,
“number”, “boolean”,
string or “string”, and “null”.
array of
type all types
unique MongoDB’s implementation of
strings the JSON Schema does not
support the “integer” type.
Use the bsonType keyword
and the “int” or “long” types
instead.

array of
JSON Field must match all specified
allOf all types
Schema schemas
objects

array of
Field must match at least one
anyOf all types JSON
of the specified schemas
Schema

80
Keyword Type Definition Behavior

objects

array of
JSON Field must match exactly one
oneOf all types
Schema of the specified schemas
objects

a JSON
Field must not match the
not all types Schema
schema
object

number Field must be a multiple of this


multipleOf number
s value

number Indicates the maximum value


maximum number
s of the field

If true and field is a


number, maximum is an
number
exclusiveMaximum boolean exclusive maximum.
s
Otherwise, it is an inclusive
maximum.

number Indicates the minimum value


minimum number
s of the field

If true, minimum is an
number exclusive minimum.
exclusiveMinimum boolean
s Otherwise, it is an inclusive
minimum.

81
Keyword Type Definition Behavior

Indicates the maximum length


maxLength strings integer
of the field

Indicates the minimum length


minLength strings integer
of the field

string
Field must match the regular
pattern strings containin
expression
g a regex

Indicates the field’s maximum


maxProperties objects integer
number of properties

Indicates the field’s minimum


minProperties objects integer
number of properties

array of Object’s property set must


required objects unique contain all the specified
strings elements in the array

If true, additional fields are


allowed. If false, they are
not. If a valid JSON Schema
additionalPropertie boolean object is specified, additional
objects
s or object fields must validate against the
schema.

Defaults to true.

82
Keyword Type Definition Behavior

A valid JSON Schema where


properties objects object each value is also a valid JSON
Schema object

In addition
to properties requirements
patternProperties objects object , each property name of this
object must be a valid regular
expression

Describes field or schema


dependencies objects object
dependencies

boolean If an object, must be a valid


additionalItems arrays
or object JSON Schema

Must be either a valid JSON


object or
items arrays Schema, or an array of valid
array
JSON Schemas

Indicates the maximum length


maxItems arrays integer
of array

Indicates the minimum length


minItems arrays integer
of array

If true, each item in the array


must be unique. Otherwise, no
uniqueItems arrays boolean
uniqueness constraint is
enforced.

83
Keyword Type Definition Behavior

A descriptive title string with


title N/A string
no effect.

A string that describes the


description N/A string
schema and has no effect.

Extensions

MongoDB’s implementation of JSON Schema includes the


addition of the bsonType keyword, which allows you to use
all BSON types in the $jsonSchema operator. bsonType accepts
the same string aliases used for the $type operator.

Omissions

The following are not supported in MongoDB’s implementation of


JSON Schema:

 Hypertext definitions in draft 4 of the JSON Schema spec.


 The keywords:
o $ref
o $schema
o default
o definitions
o format
o id
 The integer type. You must use
the BSON type int or long with the bsonType keyword.
 Hypermedia and linking properties of JSON Schema,
including the use of JSON References and JSON Pointers.
 Unknown keywords.

84
$mod
On this page

 Examples

$mod

Select documents where the value of a field divided by a divisor


has the specified remainder (i.e. perform a modulo operation to
select documents). To specify a $mod expression, use the
following syntax:

copy

copied

{ field: { $mod: [ divisor, remainder ] } }

The $mod operator errors when passed an array with fewer or


more than two elements. See Not Enough Elements
Error and Too Many Elements Error for details.

Examples

Use $mod to Select Documents

Consider a collection inventory with the following documents:

copy

copied

{ "_id" : 1, "item" : "abc123", "qty" : 0 }


{ "_id" : 2, "item" : "xyz123", "qty" : 5 }
{ "_id" : 3, "item" : "ijk123", "qty" : 12 }

85
Then, the following query selects those documents in
the inventory collection where value of the qty field
modulo 4 equals 0:

copy

copied

db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )

The query returns the following documents:

copy

copied

{ "_id" : 1, "item" : "abc123", "qty" : 0 }


{ "_id" : 3, "item" : "ijk123", "qty" : 12 }

Not Enough Elements Error

The $mod operator errors when passed an array with fewer than
two elements.

Array with Single Element

The following operation incorrectly passes the $mod operator an


array that contains a single element:

copy

copied

db.inventory.find( { qty: { $mod: [ 4 ] } } )

The statement results in the following error:

copy

86
copied

error: {
"$err" : "bad query: BadValue malformed mod, not
enough elements",
"code" : 16810
}

Empty Array

The following operation incorrectly passes the $mod operator an


empty array:

copy

copied

db.inventory.find( { qty: { $mod: [ ] } } )

The statement results in the following error:

copy

copied

error: {
"$err" : "bad query: BadValue malformed mod, not
enough elements",
"code" : 16810
}

Too Many Elements Error

The $mod operator errors when passed an array with more than
two elements.

For example, the following operation attempts to use


the $mod operator with an array that contains four elements:

87
copy

copied

error: {
"$err" : "bad query: BadValue malformed mod, too
many elements",
"code" : 16810
}

88
$regex
On this page

 Definition
 Behavior
 Examples

Definition

$regex

Provides regular expression capabilities for pattern


matching strings in queries. MongoDB uses Perl compatible
regular expressions (i.e. “PCRE” ) version 8.42 with UTF-8
support.

To use $regex, use one of the following syntaxes:

copy

copied

{ <field>: { $regex: /pattern/, $options: '<options


>' } }
{ <field>: { $regex: 'pattern', $options: '<options
>' } }
{ <field>: { $regex: /pattern/<options> } }

In MongoDB, you can also use regular expression objects


(i.e. /pattern/) to specify regular expressions:

copy

copied

89
{ <field>: /pattern/<options> }

For restrictions on particular syntax use, see $regex vs. /pattern/


Syntax.

$options

The following <options> are available for use with regular


expression.

Optio
Description Syntax Restrictions
n

Case insensitivity to
match upper and lower
cases. For an example,
i
see Perform Case-
Insensitive Regular
Expression Match.

For patterns that


include anchors
(i.e. ^ for the
start, $ for the end),
m match at the beginning
or end of each line for
strings with multiline
values. Without this
option, these anchors
match at beginning or

90
Optio
Description Syntax Restrictions
n

end of the string. For an


example, see Multiline
Match for Lines
Starting with Specified
Pattern.

If the pattern contains


no anchors or if the
string value has no
newline characters
(e.g. \n), the m option
has no effect.

“Extended” capability
to ignore all white space
characters in
the $regex pattern
unless escaped or
included in a character
class. Requires $regex with $options s
x
yntax
Additionally, it ignores
characters in-between
and including an un-
escaped hash/pound (#)
character and the next
new line, so that you
may include comments

91
Optio
Description Syntax Restrictions
n

in complicated patterns.
This only applies to
data characters; white
space characters may
never appear within
special character
sequences in a pattern.

The x option does not


affect the handling of
the VT character (i.e.
code 11).

Allows the dot character


(i.e. .) to match all
characters including new
Requires $regex with $options s
s line characters. For an
yntax
example, see Use the .
Dot Character to Match
New Line.

NOTE
The $regex operator does not support the global search
modifier g.

Behavior

$regex vs. /pattern/ Syntax

92
$in Expressions

To include a regular expression in an $in query expression, you


can only use JavaScript regular expression objects
(i.e. /pattern/ ). For example:

copy

copied

{ name: { $in: [ /^acme/i, /^ack/ ] } }

You cannot use $regex operator expressions inside an $in.

Implicit AND Conditions for the Field

To include a regular expression in a comma-separated list of


query conditions for the field, use the $regex operator. For
example:

copy

copied

{ name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcor


p' ] } }
{ name: { $regex: /acme.*corp/, $options: 'i', $nin:
[ 'acmeblahcorp' ] } }
{ name: { $regex: 'acme.*corp', $options: 'i', $nin:
[ 'acmeblahcorp' ] } }

x and s Options

To use either the x option or s options, you must use


the $regex operator expression with the $options operator. For
example, to specify the i and the s options, you must
use $options for both:

93
copy

copied

{ name: { $regex: /acme.*corp/, $options: "si" } }


{ name: { $regex: 'acme.*corp', $options: "si" } }

PCRE vs JavaScript

To use PCRE supported features in the regex pattern that are


unsupported in JavaScript, you must use the $regex operator
expression with the pattern as a string. For example, to
use (?i) in the pattern to turn case-insensitivity on for the
remaining pattern and (?-i) to turn case-sensitivity on for the
remaining pattern, you must use the $regex operator with the
pattern as a string:

copy

copied

{ name: { $regex: '(?i)a(?-i)cme' } }

$regex and $not

Starting in 4.0.7, $not operator can perform logical NOT operation


on both:

 regular expression objects (i.e. /pattern/)


For example:

copy

copied

db.inventory.find( { item: { $not: /^p.*/ } } )


 $regex operator expressions (starting in MongoDB 4.0.7).
For example:

94
copy

copied

db.inventory.find( { item: { $not: { $regex: "^p


.*" } } } )
db.inventory.find( { item: { $not: { $regex: /^p
.*/ } } } )

In 4.0.6 and earlier, you could use $not operator with regular
expression objects (i.e. /pattern/) but not with $regex operator
expressions.

Index Use

For case sensitive regular expression queries, if an index exists


for the field, then MongoDB matches the regular expression
against the values in the index, which can be faster than a
collection scan. Further optimization can occur if the regular
expression is a “prefix expression”, which means that all potential
matches start with the same string. This allows MongoDB to
construct a “range” from that prefix and only match against those
values from the index that fall within that range.

A regular expression is a “prefix expression” if it starts with a


caret (^) or a left anchor (\A), followed by a string of simple
symbols. For example, the regex /^abc.*/ will be optimized by
matching only against the values from the index that start
with abc.

Additionally, while /^a/, /^a.*/, and /^a.*$/ match equivalent


strings, they have different performance characteristics. All of
these expressions use an index if an appropriate index exists;
however, /^a.*/, and /^a.*$/ are slower. /^a/ can stop
scanning after matching the prefix.

95
Case insensitive regular expression queries generally cannot use
indexes effectively. The $regex implementation is not collation-
aware and is unable to utilize case-insensitive indexes.

Examples

The following examples use a collection products with the


following documents:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "Fir
st line\nSecond line" }
{ "_id" : 102, "sku" : "xyz456", "description" : "Man
y spaces before line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Mul
tiple\nline description" }

Perform a LIKE Match

The following example matches all documents where the sku field
is like "%789":

copy

copied

db.products.find( { sku: { $regex: /789$/ } } )

The example is analogous to the following SQL LIKE statement:

copy

copied

96
SELECT * FROM products
WHERE sku like "%789";

Perform Case-Insensitive Regular Expression Match

The following example uses the i option perform a case-


insensitive match for documents with sku value that starts
with ABC.

copy

copied

db.products.find( { sku: { $regex: /^ABC/i } } )

The query matches the following documents:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "Fir
st line\nSecond line" }

Multiline Match for Lines Starting with Specified Pattern

The following example uses the m option to match lines starting


with the letter S for multiline strings:

copy

copied

db.products.find( { description: { $regex: /^S/, $opt


ions: 'm' } } )

97
The query matches the following documents:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "Fir
st line\nSecond line" }

Without the m option, the query would match just the following
document:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }

If the $regex pattern does not contain an anchor, the pattern


matches against the string as a whole, as in the following
example:

copy

copied

db.products.find( { description: { $regex: /S/ } } )

Then, the $regex would match both documents:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }

98
{ "_id" : 101, "sku" : "abc789", "description" : "Fir
st line\nSecond line" }

Use the . Dot Character to Match New Line

The following example uses the s option to allow the dot character
(i.e. .) to match all characters including new line as well as
the i option to perform a case-insensitive match:

copy

copied

db.products.find( { description: { $regex: /m.*line/,


$options: 'si' } } )

The query matches the following documents:

copy

copied

{ "_id" : 102, "sku" : "xyz456", "description" : "Man


y spaces before line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Mul
tiple\nline description" }

Without the s option, the query would have matched only the
following document:

copy

copied

{ "_id" : 102, "sku" : "xyz456", "description" : "Man


y spaces before line" }

Ignore White Spaces in Pattern

99
The following example uses the x option ignore white spaces and
the comments, denoted by the # and ending with the \n in the
matching pattern:

copy

copied

var pattern = "abc #category code\n123 #item number"


db.products.find( { sku: { $regex: pattern, $options:
"x" } } )

The query matches the following document:

copy

copied

{ "_id" : 100, "sku" : "abc123", "description" : "Sin


gle line description." }

100
$text
On this page

 Definition
 Behavior
 Examples

MONGODB ATLAS SEARCH


Atlas Search makes it easy to build fast, relevance-based search
capabilities on top of your MongoDB data. Try it today on MongoDB
Atlas, our fully managed database as a service.

Definition

$text

$text performs a text search on the content of the fields


indexed with a text index. A $text expression has the following
syntax:

Changed in version 3.2.

copy

copied

{
$text:
{
$search: <string>,
$language: <string>,
$caseSensitive: <boolean>,
$diacriticSensitive: <boolean>
}

101
}

The $text operator accepts a text query document with the


following fields:

Field Type Description

A string of terms that MongoDB


parses and uses to query the text
index. MongoDB performs a
$search string logical OR search of the terms unless
specified as a phrase.
See Behavior for more information
on the field.

Optional. The language that


determines the list of stop words for
the search and the rules for the
stemmer and tokenizer. If not
specified, the search uses the default
language of the index. For
$language string supported languages, see Text
Search Languages.

If you specify a language value


of "none", then the text search
uses simple tokenization with no list
of stop words and no stemming.

102
Field Type Description

Optional. A boolean flag to enable


or disable case sensitive search.
Defaults to false; i.e. the search
defers to the case insensitivity of
boolea the text index.
$caseSensitive
n
For more information, see Case
Insensitivity.

New in version 3.2.

Optional. A boolean flag to enable


or disable diacritic sensitive search
against version 3 text indexes.
Defaults to false; i.e. the search
defers to the diacritic insensitivity
of the text index.

$diacriticSensitiv boolea Text searches against earlier


e n versions of the text index are
inherently diacritic sensitive and
cannot be diacritic insensitive. As
such,
the $diacriticSensitive optio
n has no effect with earlier versions
of the text index.

For more information, see Diacritic

103
Field Type Description

Insensitivity.

New in version 3.2.

The $text operator, by default, does not return results sorted in


terms of the results’ scores. For more information on sorting by
the text search scores, see the Text Score documentation.

Behavior

Restrictions

 A query can specify, at most, one $text expression.


 The $text query can not appear in $nor expressions.
 The $text query can not appear in $elemMatch query expressions
or $elemMatch projection expressions.
 To use a $text query in an $or expression, all clauses in
the $or array must be indexed.
 You cannot use hint() if the query includes a $text query
expression.
 You cannot specify $natural sort order if the query includes
a $text expression.
 You cannot combine the $text expression, which requires a
special text index, with a query operator that requires a different type
of special index. For example you cannot combine $text expression
with the $near operator.
 Views do not support text search.

If using the $text operator in aggregation, the following


restrictions also apply.

104
 The $match stage that includes a $text must be
the first stage in the pipeline.
 A text operator can only occur once in the stage.
 The text operator expression cannot appear
in $or or $not expressions.
 The text search, by default, does not return the matching
documents in order of matching scores. To sort by
descending score, use the $meta aggregation expression in
the $sort stage.

$search Field

In the $search field, specify a string of words that


the text operator parses and uses to query the text index.

The text operator treats most punctuation in the string as


delimiters, except a hyphen-minus (-) that negates term or an
escaped double quotes \" that specifies a phrase.

Phrases

To match on a phrase, as opposed to individual terms, enclose the


phrase in escaped double quotes (\"), as in:

copy

copied

"\"ssl certificate\""

If the $search string includes a phrase and individual terms, text


search will only match the documents that include the phrase.

For example, passed a $search string:

copy

copied

105
"\"ssl certificate\" authority key"

The $text operator searches for the phrase "ssl certificate".

Negations

Prefixing a word with a hyphen-minus (-) negates a word:

 The negated word excludes documents that contain the


negated word from the result set.
 When passed a search string that only contains negated
words, text search will not match any documents.
 A hyphenated word, such as pre-market, is not a negation.
If used in a hyphenated word, $text operator treats the
hyphen-minus (-) as a delimiter. To negate the
word market in this instance, include a space
between pre and -market, i.e., pre -market.

The $text operator adds all negations to the query with the
logical AND operator.

Match Operation

Stop Words

The $text operator ignores language-specific stop words, such


as the and and in English.

Stemmed Words

For case insensitive and diacritic insensitive text searches,


the $text operator matches on the complete stemmed word. So if
a document field contains the word blueberry, a search on the
term blue will not match.
However, blueberry or blueberries will match.

106
Case Sensitive Search and Stemmed Words

For case sensitive search (i.e. $caseSensitive: true), if the


suffix stem contains uppercase letters, the $text operator
matches on the exact word.

Diacritic Sensitive Search and Stemmed Words

For diacritic sensitive search (i.e. $diacriticSensitive: true),


if the suffix stem contains the diacritic mark or marks,
the $text operator matches on the exact word.

Case Insensitivity

Changed in version 3.2.

The $text operator defaults to the case insensitivity of


the text index:

 The version 3 text index is case insensitive for Latin


characters with or without diacritics and characters from
non-Latin alphabets, such as the Cyrillic alphabet.
See text index for details.
 Earlier versions of the text index are case insensitive for
Latin characters without diacritic marks; i.e. for [A-z].

$caseSensitive Option

To support case sensitive search where the text index is case


insensitive, specify $caseSensitive: true.

Case Sensitive Search Process

When performing a case sensitive search


($caseSensitive: true) where the text index is case
insensitive, the $text operator:

107
 First searches the text index for case insensitive and
diacritic matches.
 Then, to return just the documents that match the case of the
search terms, the $text query operation includes an
additional stage to filter out the documents that do not match
the specified case.

For case sensitive search (i.e. $caseSensitive: true), if the


suffix stem contains uppercase letters, the $text operator
matches on the exact word.

Specifying $caseSensitive: true may impact performance.

SEE ALSO
Stemmed Words

Diacritic Insensitivity

Changed in version 3.2.

The $text operator defaults to the diacritic insensitivity of


the text index:

 The version 3 text index is diacritic insensitive. That is, the


index does not distinguish between characters that contain
diacritical marks and their non-marked counterpart, such
as é, ê, and e.
 Earlier versions of the text index are diacritic sensitive.

$diacriticSensitive Option

To support diacritic sensitive text search against the version


3 text index, specify $diacriticSensitive: true.

Text searches against earlier versions of the text index are


inherently diacritic sensitive and cannot be diacritic insensitive.
As such, the $diacriticSensitive option for

108
the $text operator has no effect with earlier versions of
the text index.

Diacritic Sensitive Search Process

To perform a diacritic sensitive text search


($diacriticSensitive: true) against a version 3 text index,
the $text operator:

 First searches the text index, which is diacritic insensitive.


 Then, to return just the documents that match the diacritic
marked characters of the search terms, the $text query
operation includes an additional stage to filter out the
documents that do not match.

Specifying $diacriticSensitive: true may impact


performance.

To perform a diacritic sensitive search against an earlier version


of the text index, the $text operator searches the text index
which is diacritic sensitive.

For diacritic sensitive search, if the suffix stem contains the


diacritic mark or marks, the $text operator matches on the exact
word.

SEE ALSO
Stemmed Words

Text Score

The $text operator assigns a score to each document that


contains the search term in the indexed fields. The score
represents the relevance of a document to a given text search
query. The score can be part of a sort() method specification as
well as part of the projection expression.
The { $meta: "textScore" } expression provides information

109
on the processing of the $text operation. See $meta projection
operator for details on accessing the score for projection or sort.

Examples

The following examples assume a collection articles that has


a version 3 text index on the field subject:

copy

copied

db.articles.createIndex( { subject: "text" } )

Populate the collection with the following documents:

copy

copied

db.articles.insert(
[
{ _id: 1, subject: "coffee", author: "xyz", view
s: 50 },
{ _id: 2, subject: "Coffee Shopping", author: "e
fg", views: 5 },
{ _id: 3, subject: "Baking a cake", author: "abc
", views: 90 },
{ _id: 4, subject: "baking", author: "xyz", view
s: 100 },
{ _id: 5, subject: "Café Con Leche", author: "ab
c", views: 200 },
{ _id: 6, subject: "Сырники", author: "jkl", vie
ws: 80 },
{ _id: 7, subject: "coffee and cream", author: "
efg", views: 10 },

110
{ _id: 8, subject: "Cafe con Leche", author: "xy
z", views: 10 }
]
)

Search for a Single Word

The following query specifies a $search string of coffee:

copy

copied

db.articles.find( { $text: { $search: "coffee" } } )

This query returns the documents that contain the term coffee in
the indexed subject field, or more precisely, the stemmed version
of the word:

copy

copied

{ "_id" : 2, "subject" : "Coffee Shopping", "author"


: "efg", "views" : 5 }
{ "_id" : 7, "subject" : "coffee and cream", "author"
: "efg", "views" : 10 }
{ "_id" : 1, "subject" : "coffee", "author" : "xyz",
"views" : 50 }
SEE ALSO
Case Insensitivity, Stemmed Words

Match Any of the Search Terms

If the search string is a space-delimited string, $text operator


performs a logical OR search on each term and returns documents
that contains any of the terms.

111
The following query specifies a $search string of three terms
delimited by space, "bake coffee cake":

copy

copied

db.articles.find( { $text: { $search: "bake coffee ca


ke" } } )

This query returns documents that contain


either bake or coffee or cake in the indexed subject field, or
more precisely, the stemmed version of these words:

copy

copied

{ "_id" : 2, "subject" : "Coffee Shopping", "author"


: "efg", "views" : 5 }
{ "_id" : 7, "subject" : "coffee and cream", "author"
: "efg", "views" : 10 }
{ "_id" : 1, "subject" : "coffee", "author" : "xyz",
"views" : 50 }
{ "_id" : 3, "subject" : "Baking a cake", "author" :
"abc", "views" : 90 }
{ "_id" : 4, "subject" : "baking", "author" : "xyz",
"views" : 100 }
SEE ALSO
Case Insensitivity, Stemmed Words

Search for a Phrase

To match the exact phrase as a single term, escape the quotes.

The following query searches for the phrase coffee shop:

copy

112
copied

db.articles.find( { $text: { $search: "\"coffee shop\


"" } } )

This query returns documents that contain the


phrase coffee shop:

copy

copied

{ "_id" : 2, "subject" : "Coffee Shopping", "author"


: "efg", "views" : 5 }
SEE ALSO
Phrases

Exclude Documents That Contain a Term

A negated term is a term that is prefixed by a minus sign -. If you


negate a term, the $text operator will exclude the documents that
contain those terms from the results.

The following example searches for documents that contain the


words coffee but do not contain the term shop, or more precisely
the stemmed version of the words:

copy

copied

db.articles.find( { $text: { $search: "coffee -shop"


} } )

The query returns the following documents:

copy

copied

113
{ "_id" : 7, "subject" : "coffee and cream", "author"
: "efg", "views" : 10 }
{ "_id" : 1, "subject" : "coffee", "author" : "xyz",
"views" : 50 }
SEE ALSO
Negations, Stemmed Words

Search a Different Language

Use the optional $language field in the $text expression to


specify a language that determines the list of stop words and the
rules for the stemmer and tokenizer for the search string.

If you specify a language value of "none", then the text search


uses simple tokenization with no list of stop words and no
stemming.

The following query specifies es, i.e. Spanish, as the language that
determines the tokenization, stemming, and stop words:

copy

copied

db.articles.find(
{ $text: { $search: "leche", $language: "es" } }
)

The query returns the following documents:

copy

copied

{ "_id" : 5, "subject" : "Café Con Leche", "author" :


"abc", "views" : 200 }
{ "_id" : 8, "subject" : "Cafe con Leche", "author" :
"xyz", "views" : 10 }

114
The $text expression can also accept the language by
name, spanish. See Text Search Languages for the supported
languages.

SEE ALSO
Case Insensitivity

Case and Diacritic Insensitive Search

Changed in version 3.2.

The $text operator defers to the case and diacritic insensitivity of


the text index. The version 3 text index is diacritic insensitive
and expands its case insensitivity to include the Cyrillic alphabet
as well as characters with diacritics. For details, see text Index
Case Insensitivity and text Index Diacritic Insensitivity.

The following query performs a case and diacritic insensitive text


search for the terms ырники or CAFÉS:

copy

copied

db.articles.find( { $text: { $search: " ырники CAFÉS"


} } )

Using the version 3 text index, the query matches the following
documents.

copy

copied

{ "_id" : 6, "subject" : "Сырники", "author" : "jkl",


"views" : 80 }
{ "_id" : 5, "subject" : "Café Con Leche", "author" :
"abc", "views" : 200 }

115
{ "_id" : 8, "subject" : "Cafe con Leche", "author" :
"xyz", "views" : 10 }

With the previous versions of the text index, the query would not
match any document.

SEE ALSO
Case Insensitivity, Diacritic Insensitivity, Stemmed Words, Text
Indexes

Perform Case Sensitive Search

Changed in version 3.2.

To enable case sensitive search, specify $caseSensitive: true.


Specifying $caseSensitive: true may impact performance.

Case Sensitive Search for a Term

The following query performs a case sensitive search for the


term Coffee:

copy

copied

db.articles.find( { $text: { $search: "Coffee", $case


Sensitive: true } } )

The search matches just the document:

copy

copied

{ "_id" : 2, "subject" : "Coffee Shopping", "author"


: "efg", "views" : 5 }
SEE ALSO

116
Case Insensitivity, Case Sensitive Search and Stemmed Words

Case Sensitive Search for a Phrase

The following query performs a case sensitive search for the


phrase Café Con Leche:

copy

copied

db.articles.find( {
$text: { $search: "\"Café Con Leche\"", $caseSensi
tive: true }
} )

The search matches just the document:

copy

copied

{ "_id" : 5, "subject" : "Café Con Leche", "author" :


"abc", "views" : 200 }
SEE ALSO
Case Sensitive Search and Stemmed Words, Case Insensitivity

Case Sensitivity with Negated Term

A negated term is a term that is prefixed by a minus sign -. If you


negate a term, the $text operator will exclude the documents that
contain those terms from the results. You can also specify case
sensitivity for negated terms.

The following example performs a case sensitive search for


documents that contain the word Coffee but do not contain the
lower-case term shop, or more precisely the stemmed version of
the words:

117
copy

copied

db.articles.find( { $text: { $search: "Coffee -shop",


$caseSensitive: true } } )

The query matches the following document:

copy

copied

{ "_id" : 2, "subject" : "Coffee Shopping", "author"


: "efg" }
SEE ALSO
Case Sensitive Search and Stemmed Words, Negations

Diacritic Sensitive Search

Changed in version 3.2.

To enable diacritic sensitive search against a version 3 text index,


specify $diacriticSensitive: true.
Specifying $diacriticSensitive: true may impact
performance.

Diacritic Sensitive Search for a Term

The following query performs a diacritic sensitive text search on


the term CAFÉ, or more precisely the stemmed version of the word:

copy

copied

db.articles.find( { $text: { $search: "CAFÉ", $diacri


ticSensitive: true } } )

118
The query only matches the following document:

copy

copied

{ "_id" : 5, "subject" : "Café Con Leche", "author" :


"abc" }
SEE ALSO
Diacritic Sensitive Search and Stemmed Words, Diacritic
Insensitivity, Case Insensitivity

Diacritic Sensitivity with Negated Term

The $diacriticSensitive option applies also to negated terms.


A negated term is a term that is prefixed by a minus sign -. If you
negate a term, the $text operator will exclude the documents that
contain those terms from the results.

The following query performs a diacritic sensitive text search for


document that contains the term leches but not the term cafés,
or more precisely the stemmed version of the words:

copy

copied

db.articles.find(
{ $text: { $search: "leches -cafés", $diacriticSens
itive: true } }
)

The query matches the following document:

copy

copied

119
{ "_id" : 8, "subject" : "Cafe con Leche", "author" :
"xyz" }
SEE ALSO
Diacritic Sensitive Search and Stemmed Words, Diacritic
Insensitivity, Case Insensitivity

Text Search Score Examples

Return the Text Search Score

The following query performs a text search for the term cake and
uses the $meta operator in the projection document to append the
relevance score to each matching document:

copy

copied

db.articles.find(
{ $text: { $search: "cake" } },
{ score: { $meta: "textScore" } }
)

The returned document includes an additional field score that


contains the document’s relevance score:

{ "_id" : 3, "subject" : "Baking a cake", "author" :


"abc", "views" : 90, "score" : 0.75 }
SEE ALSO
$meta

Sort by Text Search Score

 Starting in MongoDB 4.4, you can specify


the { $meta: "textScore" } expression in the sort() without
also specifying the expression in the projection. For example,

copy
120
copied

db.articles.find(
{ $text: { $search: "cake" } }
).sort( { score: { $meta: "textScore" } } )
As a result, you can sort the resulting documents by their search
relevance without projecting the textScore.

In earlier versions, to include { $meta: "textScore" } expression


in the sort(), you must also include the same expression in the
projection.

 Starting in MongoDB 4.4, if you include


the { $meta: "textScore" } expression in both
the projection and sort(), the projection and sort documents can
have different field names for the expression.

For example, in the following operation, the projection uses a field


named score for the expression and the sort() uses the field
named ignoredName.

copy

copied

db.articles.find(
{ $text: { $search: "cake" } } ,
{ score: { $meta: "textScore" } }
).sort( { ignoredName: { $meta: "textScore" } } )
In previous versions of MongoDB, if { $meta: "textScore" } is
included in both the projection and sort, you must specify the same
field name for the expression.
 In MongoDB 4.2 and earlier, to sort by the text score, include
the same $meta expression in both the projection document and the
sort expression. The following query searches for the
term coffee and sorts the results by the descending score:

copy

121
copied

db.articles.find(
{ $text: { $search: "coffee" } },
{ score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )
The query returns the matching documents sorted by descending
score.
SEE ALSO
$meta

Return Top 2 Matching Documents

Use the limit() method in conjunction with a sort() to return


the top n matching documents.

The following query searches for the term coffee and sorts the
results by the descending score, limiting the results to the top two
matching documents:

copy

copied

db.articles.find(
{ $text: { $search: "coffee" } },
{ score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } ).limit(2)
SEE ALSO
$meta

Text Search with Additional Query and Sort Expressions

The following query searches for documents where


the author equals "xyz" and the indexed field subject contains
the terms coffee or bake. The operation also specifies a sort
order of ascending date, then descending text search score:

122
copy

copied

db.articles.find(
{ author: "xyz", $text: { $search: "coffee bake" }
},
{ score: { $meta: "textScore" } }
).sort( { date: 1, score: { $meta: "textScore" } } )

123
$where
On this page

 Definition
 Behavior
o Available JavaScript Properties and Functions
o elemMatch
o Considerations
o JavaScript Enablement
 Example

Definition

$where

Use the $where operator to pass either a string containing a


JavaScript expression or a full JavaScript function to the query
system. The $where provides greater flexibility, but requires that
the database processes the JavaScript expression or function
for each document in the collection. Reference the document in
the JavaScript expression or function using either this or obj .

copy
copied
{ $where: <string|JavaScript Code> }

NOTE
Starting in MongoDB 4.4, $where no longer supports the
deprecated BSON type JavaScript code with scope (BSON type
15). The $where operator only supports BSON type String (BSON
type 2) or BSON type JavaScript (BSON type 13). The use of BSON
type JavaScript with scope for $where has been deprecated since
MongoDB 4.2.1.
AGGREGATION ALTERNATIVES PREFERRED

124
Starting in MongoDB 3.6, the $expr operator allows the use
of aggregation expressions within the query language. And,
starting in MongoDB 4.4, the $function and $accumulator allows
users to define custom aggregation expressions in JavaScript if
the provided pipeline operators cannot fulfill your application’s
needs.
Given the available aggregation operators:

 The use of $expr with aggregation operators that do not use


JavaScript (i.e. non-$function and non-$accumulator operators)
is faster than $where because it does not execute JavaScript
and should be preferred if possible.
 However, if you must create custom expressions, $function is
preferred over $where.

Behavior

Available JavaScript Properties and Functions

map-reduce operations and $where operator


expressions cannot access certain global functions or properties,
such as db, that are available in the mongo shell.

The following JavaScript functions and properties are


available to map-reduce operations and $where operator
expressions:

Available Properties Available Functions

args assert() Map()

MaxKey BinData() MD5()

125
Available Properties Available Functions

MinKey DBPointer() NumberInt()

DBRef() NumberLong()

doassert() ObjectId()

emit() print()

gc() printjson()

HexData() printjsononeline()

hex_md5() sleep()

isNumber() Timestamp()

isObject() tojson()

ISODate() tojsononeline()

isString() tojsonObject()

UUID()

version()

elemMatch

126
Only apply the $where query operator to top-level documents.
The $where query operator will not work inside a nested document,
for instance, in an $elemMatch query.

Considerations

 Do not use global variables.


 $where evaluates JavaScript and cannot take advantage of indexes.
Therefore, query performance improves when you express your
query using the standard MongoDB operators (e.g., $gt, $in).
 In general, you should use $where only when you cannot express
your query using another operator. If you must use $where, try to
include at least one other standard query operator to filter the result
set. Using $where alone requires a collection scan.

Using normal non-$where query statements provides the following


performance advantages:

 MongoDB will evaluate non-$where components of query


before $where statements. If the non-$where statements
match no documents, MongoDB will not perform any query
evaluation using $where.
 The non-$where query statements may use an index.

JavaScript Enablement

To use $where (or $function, $accumulator, or mapReduce), you must


have server-side scripting enabled (default).

However, if you do not use these operations, disable server-side


scripting:

 For a mongod instance,


see security.javascriptEnabled configuration option or --
noscripting command-line option.
 For a mongos instance,
see security.javascriptEnabled configuration option or the --
noscripting command-line option starting in MongoDB 4.4.

127
In earlier versions, MongoDB does not allow JavaScript
execution on mongos instances.

See also ➤ Run MongoDB with Secure Configuration Options.

Example

Consider the following documents in the players collection:

copy
copied
db.players.insertMany([
{ _id: 12378, name: "Steve", username: "steveisawe
some", first_login: "2017-01-01" },
{ _id: 2, name: "Anya", username: "anya", first_lo
gin: "2001-02-02" }
])

The following example uses $where and the hex_md5() JavaScript


function to compare the value of the name field to an MD5 hash
and returns any matching document.

copy
copied
db.players.find( { $where: function() {
return (hex_md5(this.name) == "9b53e667f30cd329dca
1ec9e6a83e994")
} } );

The operation returns the following result:

copy
copied
{
"_id" : 2,
"name" : "Anya",
"username" : "anya",

128
"first_login" : "2001-02-02"
}

As an alternative, the previous example can be rewritten


using $expr and $function. Starting in MongoDB 4.4, you can define
custom aggregation expression in JavaScript with the aggregation
operator $function. To access $function and other aggregation
operators in db.collection.find(), use with $expr:

copy
copied
db.players.find( {$expr: { $function: {
body: function(name) { return hex_md5(name) ==
"9b53e667f30cd329dca1ec9e6a83e994"; },
args: [ "$name" ],
lang: "js"
} } } )

If you must create custom expressions, $function is preferred


over $where.

129
Geospatial Query Operators
On this page

 Operators

NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Operators

Query Selectors

Name Description

Selects geometries that intersect with


$geoIntersects a GeoJSON geometry. The 2dsphere index
supports $geoIntersects.

Selects geometries within a bounding GeoJSON


$geoWithin geometry. The 2dsphere and 2d indexes
support $geoWithin.

Returns geospatial objects in proximity to a point.


$near Requires a geospatial index.
The 2dsphere and 2d indexes support $near.

130
Name Description

Returns geospatial objects in proximity to a point on a


$nearSphere sphere. Requires a geospatial index.
The 2dsphere and 2d indexes support $nearSphere.

Geometry Specifiers

Name Description

Specifies a rectangular box using legacy coordinate pairs


$box
for $geoWithin queries. The 2d index supports $box.

Specifies a circle using legacy coordinate pairs


$center to $geoWithin queries when using planar geometry.
The 2d index supports $center.

Specifies a circle using either legacy coordinate pairs


or GeoJSON format for $geoWithin queries when using
$centerSphere
spherical geometry. The 2dsphere and 2d indexes
support $centerSphere.

131
Name Description

Specifies a geometry in GeoJSON format to geospatial


$geometry
query operators.

Specifies a maximum distance to limit the results


$maxDistance of $near and $nearSphere queries.
The 2dsphere and 2d indexes support $maxDistance.

Specifies a minimum distance to limit the results


$minDistance of $near and $nearSphere queries. For use
with 2dsphere index only.

Specifies a polygon to using legacy coordinate pairs


$polygon for $geoWithin queries. The 2d index
supports $center.

Deprecated. Modifies a $geoWithin and $near queries


$uniqueDocs to ensure that even if a document matches the query
multiple times, the query returns the document once.

132
$geoIntersects
On this page

 Definition
 Behavior
 Examples

Definition

$geoIntersects

Selects documents whose geospatial data intersects with a


specified GeoJSON object; i.e. where the intersection of the data
and the specified object is non-empty.

The $geoIntersects operator uses the $geometry operator to


specify the GeoJSON object. To specify a GeoJSON polygons or
multipolygons using the default coordinate reference system
(CRS), use the following syntax:

copy
copied
{
<location field>: {
$geoIntersects: {
$geometry: {
type: "<GeoJSON object type>" ,
coordinates: [ <coordinates> ]
}
}
}
}

133
For $geoIntersects queries that specify GeoJSON geometries
with areas greater than a single hemisphere, the use of the
default CRS results in queries for the complementary
geometries.

To specify a single-ringed GeoJSON polygon with a custom


MongoDB CRS, use the following prototype that specifies the
custom MongoDB CRS in the $geometry expression:

copy
copied
{
<location field>: {
$geoIntersects: {
$geometry: {
type: "Polygon" ,
coordinates: [ <coordinates> ],
crs: {
type: "name",
properties: { name: "urn:x-mongodb:cr
s:strictwinding:EPSG:4326" }
}
}
}
}
}

The custom MongoDB CRS uses a counter-clockwise winding


order and allows $geoIntersects to support queries with a
single-ringed GeoJSON polygon whose area is greater than or
equal to a single hemisphere. If the specified polygon is smaller
than a single hemisphere, the behavior of $geoIntersects with
the MongoDB CRS is the same as with the default CRS. See
also “Big” Polygons.

IMPORTANT

134
If specifying latitude and longitude coordinates, list
the longitude first and then latitude:

 Valid longitude values are between -180 and 180, both


inclusive.
 Valid latitude values are between -90 and 90, both
inclusive.

Behavior

Geospatial Indexes

$geoIntersects uses spherical


geometry. $geoIntersects does not require a geospatial index.
However, a geospatial index will improve query performance. Only
the 2dsphere geospatial index supports $geoIntersects.

Degenerate Geometry

$geoIntersects does not guarantee that it will consider a


polygon to intersect with its own edges; its own vertices; or
another polygon sharing vertices or edges but no interior space.

“Big” Polygons

For $geoIntersects, if you specify a single-ringed polygon that


has an area greater than a single hemisphere,
include the custom MongoDB coordinate reference system
in the $geometry expression;
otherwise, $geoIntersects queries for the complementary
geometry. For all other GeoJSON polygons with areas greater than
a hemisphere, $geoIntersects queries for the complementary
geometry.

Examples

Intersects a Polygon

135
The following example uses $geoIntersects to select
all loc data that intersect with the Polygon defined by
the coordinates array. The area of the polygon is less than the
area of a single hemisphere:

copy
copied
db.places.find(
{
loc: {
$geoIntersects: {
$geometry: {
type: "Polygon" ,
coordinates: [
[ [ 0, 0 ], [ 3, 6 ], [ 6, 1 ], [ 0, 0
] ]
]
}
}
}
}
)

For single-ringed polygons with areas greater than a single


hemisphere, see Intersects a “Big” Polygon.

Intersects a “Big” Polygon

To query with a single-ringed GeoJSON polygon whose area is


greater than a single hemisphere, the $geometry expression must
specify the custom MongoDB coordinate reference system. For
example:

copy
copied
db.places.find(
{
136
loc: {
$geoIntersects: {
$geometry: {
type : "Polygon",
coordinates: [
[
[ -100, 60 ], [ -100, 0 ], [ -100, -
60 ], [ 100, -60 ], [ 100, 60 ], [ -100, 60 ]
]
],
crs: {
type: "name",
properties: { name: "urn:x-mongodb:cr
s:strictwinding:EPSG:4326" }
}
}
}
}
}
)

137
$geoWithin
On this page

 Definition
 Behavior
 Examples

Definition

$geoWithin

Selects documents with geospatial data that exists entirely


within a specified shape.

The specified shape can be either a GeoJSON Polygon (either


single-ringed or multi-ringed), a GeoJSON MultiPolygon, or a
shape defined by legacy coordinate pairs.
The $geoWithin operator uses the $geometry operator to
specify the GeoJSON object.

To specify a GeoJSON polygons or multipolygons using the


default coordinate reference system (CRS), use the following
syntax:

copy
copied
{
<location field>: {
$geoWithin: {
$geometry: {
type: <"Polygon" or "MultiPolygon"> ,
coordinates: [ <coordinates> ]
}
}

138
}
}

For $geoWithin queries that specify GeoJSON geometries with


areas greater than a single hemisphere, the use of the default
CRS results in queries for the complementary geometries.

To specify a single-ringed GeoJSON polygon with a custom


MongoDB CRS, use the following prototype that specifies the
custom MongoDB CRS in the $geometry expression:

copy
copied
{
<location field>: {
$geoWithin: {
$geometry: {
type: "Polygon" ,
coordinates: [ <coordinates> ],
crs: {
type: "name",
properties: { name: "urn:x-mongodb:cr
s:strictwinding:EPSG:4326" }
}
}
}
}
}

The custom MongoDB CRS uses a counter-clockwise winding


order and allows $geoWithin to support queries with a single-
ringed GeoJSON polygon whose area is greater than or equal to
a single hemisphere. If the specified polygon is smaller than a
single hemisphere, the behavior of $geoWithin with the
MongoDB CRS is the same as with the default CRS. See
also “Big” Polygons.

139
If querying for inclusion in a shape defined by legacy coordinate
pairs on a plane, use the following syntax:

copy
copied
{
<location field>: {
$geoWithin: { <shape operator>: <coordinates>
}
}
}

The available shape operators are:

 $box,
 $polygon,
 $center (defines a circle), and
 $centerSphere (defines a circle on a sphere).

IMPORTANT
If you use longitude and latitude, specify coordinates in order
of longitude, latitude.

Behavior

Geospatial Indexes

$geoWithin does not require a geospatial index. However, a


geospatial index will improve query performance.
Both 2dsphere and 2d geospatial indexes support $geoWithin.

Unsorted Results

The $geoWithin operator does not return sorted results. As such,


MongoDB can return $geoWithin queries more quickly than
geospatial $near or $nearSphere queries, which sort results.

140
Degenerate Geometry

$geoWithin does not guarantee that it will consider a piece of


geometry to contain its component geometry, or another polygon
sharing its component geometry.

“Big” Polygons

For $geoWithin, if you specify a single-ringed polygon that has


an area greater than a single hemisphere,
include the custom MongoDB coordinate reference system
in the $geometry expression; otherwise, $geoWithin queries
for the complementary geometry. For all other GeoJSON polygons
with areas greater than a hemisphere, $geoWithin queries for the
complementary geometry.

Examples

Within a Polygon

The following example selects all loc data that exist entirely
within a GeoJSON Polygon. The area of the polygon is less than
the area of a single hemisphere:

copy
copied
db.places.find(
{
loc: {
$geoWithin: {
$geometry: {
type : "Polygon" ,
coordinates: [ [ [ 0, 0 ], [ 3, 6 ], [ 6
, 1 ], [ 0, 0 ] ] ]
}
}
}
141
}
)

For single-ringed polygons with areas greater than a single


hemisphere, see Within a “Big” Polygon.

Within a “Big” Polygon

To query with a single-ringed GeoJSON polygon whose area is


greater than a single hemisphere, the $geometry expression must
specify the custom MongoDB coordinate reference system. For
example:

copy
copied
db.places.find(
{
loc: {
$geoWithin: {
$geometry: {
type : "Polygon" ,
coordinates: [
[
[ -100, 60 ], [ -100, 0 ], [ -100, -
60 ], [ 100, -60 ], [ 100, 60 ], [ -100, 60 ]
]
],
crs: {
type: "name",
properties: { name: "urn:x-mongodb:cr
s:strictwinding:EPSG:4326" }
}
}
}
}
}

142
)
$within

Deprecated since version 2.4: $geoWithin replaces $within in


MongoDB 2.4.

143
$near
On this page

 Definition
 Behavior
 Examples

Definition

$near

Specifies a point for which a geospatial query returns the


documents from nearest to farthest. The $near operator can
specify either a GeoJSON point or legacy coordinate point.

$near requires a geospatial index:

 2dsphere index if specifying a GeoJSON point,


 2d index if specifying a point using legacy coordinates.

To specify a GeoJSON point, $near operator requires


a 2dsphere index and has the following syntax:

copy
copied
{
<location field>: {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ <longitude> , <latitude> ]
},

144
$maxDistance: <distance in meters>,
$minDistance: <distance in meters>
}
}
}

If specifying latitude and longitude coordinates, list


the longitude first and then latitude:

 Valid longitude values are between -180 and 180, both


inclusive.
 Valid latitude values are between -90 and 90, both
inclusive.

When specifying a GeoJSON point, you can use


the optional $minDistance and $maxDistance specifications to
limit the $near results by distance in meters:

 $minDistance limits the results to those documents that


are at least the specified distance from the center point.
 $maxDistance limits the results to those documents that
are at most the specified distance from the center point.

To specify a point using legacy coordinates, $near requires


a 2d index and has the following syntax:

copy
copied
{
$near: [ <x>, <y> ],
$maxDistance: <distance in radians>
}

When specifying a legacy coordinate, you can use


the optional $maxDistance specification to limit
the $near results by distance in radians. $maxDistance limits

145
the results to those documents that are at most the specified
distance from the center point.

Behavior

Special Indexes Restriction

You cannot combine the $near operator, which requires a


special geospatial index, with a query operator or command that
requires another special index. For example you cannot
combine $near with the $text query.

Sharded Collections

Starting in MongoDB 4.0, $near queries are supported for sharded


collections.

In earlier MongoDB versions, $near queries are not supported for


sharded collections; instead, for sharded clusters, you must use
the $geoNear aggregation stage or the geoNear command
(available in MongoDB 4.0 and earlier).

Sort Operation

$near sorts documents by distance. If you also include


a sort() for the query, sort() re-orders the matching
documents, effectively overriding the sort operation already
performed by $near. When using sort() with geospatial queries,
consider using $geoWithin operator, which does not sort
documents, instead of $near.

SEE ALSO
2d Indexes and Geospatial Near Queries

Examples

Query on GeoJSON Data

146
IMPORTANT
If specifying latitude and longitude coordinates, list
the longitude first and then latitude:

 Valid longitude values are between -180 and 180, both


inclusive.
 Valid latitude values are between -90 and 90, both inclusive.

Consider a collection places that has a 2dsphere index.

The following example returns documents that are at


least 1000 meters from and at most 5000 meters from the
specified GeoJSON point, sorted from nearest to farthest:

copy
copied
db.places.find(
{
location:
{ $near :
{
$geometry: { type: "Point", coordinates:
[ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

Query on Legacy Coordinates

IMPORTANT
If specifying latitude and longitude coordinates, list
the longitude first and then latitude:

147
 Valid longitude values are between -180 and 180, both
inclusive.
 Valid latitude values are between -90 and 90, both inclusive.

Consider a collection legacy2d that has a 2d index.

The following example returns documents that are at


most 0.10 radians from the specified legacy coordinate pair,
sorted from nearest to farthest:

copy
copied
db.legacy2d.find(
{ location : { $near : [ -73.9667, 40.78 ], $maxDi
stance: 0.10 } }
)

148
$nearSphere
On this page

 Definition
 Behavior
 Examples

Definition

$nearSphere

Specifies a point for which a geospatial query returns the


documents from nearest to farthest. MongoDB calculates
distances for $nearSphere using spherical geometry.

$nearSphere requires a geospatial index:

 2dsphere index for location data defined as GeoJSON


points
 2d index for location data defined as legacy coordinate
pairs. To use a 2d index on GeoJSON points, create the
index on the coordinates field of the GeoJSON object.

The $nearSphere operator can specify either a GeoJSON point


or legacy coordinate point.

To specify a GeoJSON Point, use the following syntax:

copy

copied

149
$nearSphere: {
$geometry: {
type : "Point",
coordinates : [ <longitude>, <latitude> ]
},
$minDistance: <distance in meters>,
$maxDistance: <distance in meters>
}
}

 The optional $minDistance limits the results to those


documents that are at least the specified distance from the
center point.
 The optional $maxDistance is available for either index.

To specify a point using legacy coordinates, use the following


syntax:

copy

copied

{
$nearSphere: [ <x>, <y> ],
$minDistance: <distance in radians>,
$maxDistance: <distance in radians>
}

 The optional $minDistance is available only if the query


uses the 2dsphere index. $minDistance limits the results
to those documents that are at least the specified distance
from the center point.
 The optional $maxDistance is available for either index.

If you use longitude and latitude for legacy coordinates, specify


the longitude first, then latitude.

SEE ALSO

150
2d Indexes and Geospatial Near Queries

Behavior

Special Indexes Restriction

You cannot combine the $nearSphere operator, which requires a


special geospatial index, with a query operator or command that
requires another special index. For example you cannot
combine $nearSphere with the $text query.

Sharded Collections

Starting in MongoDB 4.0, $nearSphere queries are supported for


sharded collections.

In earlier MongoDB versions, $nearSphere queries are not


supported for sharded collections; instead, for sharded clusters,
you must use the $geoNear aggregation stage or
the geoNear command (available in MongoDB 4.0 and earlier).

Sort Operation

$nearSphere sorts documents by distance. If you also include


a sort() for the query, sort() re-orders the matching
documents, effectively overriding the sort operation already
performed by $nearSphere. When using sort() with geospatial
queries, consider using $geoWithin operator, which does not
sort documents, instead of $nearSphere.

Examples

Specify Center Point Using GeoJSON

Consider a collection places that contains documents with


a location field and has a 2dsphere index.

151
Then, the following example returns whose location is at
least 1000 meters from and at most 5000 meters from the
specified point, ordered from nearest to farthest:

copy

copied

db.places.find(
{
location: {
$nearSphere: {
$geometry: {
type : "Point",
coordinates : [ -73.9667, 40.78 ]
},
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

Specify Center Point Using Legacy Coordinates

2d Index

Consider a collection legacyPlaces that contains documents


with legacy coordinates pairs in the location field and has
a 2d index.

Then, the following example returns those documents


whose location is at most 0.10 radians from the specified point,
ordered from nearest to farthest:

copy

152
copied

db.legacyPlaces.find(
{ location : { $nearSphere : [ -73.9667, 40.78 ],
$maxDistance: 0.10 } }
)

2dsphere Index

If the collection has a 2dsphere index instead, you can also


specify the optional $minDistance specification. For example, the
following example returns the documents whose location is at
least 0.0004 radians from the specified point, ordered from
nearest to farthest:

copy

copied

db.legacyPlaces.find(
{ location : { $nearSphere : [ -73.9667, 40.78 ],
$minDistance: 0.0004 } }
)

153
$box
On this page

 Definition
 Behavior
 Example

Definition

$box

Specifies a rectangle for a geospatial $geoWithin query to


return documents that are within the bounds of the rectangle,
according to their point-based location data. When used with
the $box operator, $geoWithin returns documents based
on grid coordinates and does not query for GeoJSON shapes.

To use the $box operator, you must specify the bottom left and
top right corners of the rectangle in an array object:

copy
copied
{
<location field>: {
$geoWithin: {
$box: [
[ <bottom left coordinates> ],
[ <upper right coordinates> ]
]
}
}
}

154
IMPORTANT
If you use longitude and latitude, specify longitude first.

Behavior

The query calculates distances using flat (planar) geometry.

Applications can use $box without having a geospatial index.


However, geospatial indexes support much faster queries than the
unindexed equivalents.

Only the 2d geospatial index supports $box.

Example

The following example query returns all documents that are within
the box having points
at: [ 0 , 0 ], [ 0 , 100 ], [ 100 , 0 ],
and [ 100 , 100 ].

copy
copied
db.places.find( {
loc: { $geoWithin: { $box: [ [ 0, 0 ], [ 100, 100
] ] } }
} )

155
$center
On this page

 Definition
 Behavior
 Example

Definition

$center

The $center operator specifies a circle for


a $geoWithin query. The query returns legacy coordinate pairs
that are within the bounds of the circle. The operator
does not return GeoJSON objects.

To use the $center operator, specify an array that contains:

 The grid coordinates of the circle’s center point, and


 The circle’s radius, as measured in the units used by the
coordinate system.

copy
copied
{
<location field>: {
$geoWithin: { $center: [ [ <x>, <y> ] , <radi
us> ] }
}
}

IMPORTANT
If you use longitude and latitude, specify longitude first.

156
Behavior

The query calculates distances using flat (planar) geometry.

Applications can use $center without having a geospatial index.


However, geospatial indexes support much faster queries than the
unindexed equivalents.

Only the 2d geospatial index supports $center.

Example

The following example query returns all documents that have


coordinates that exist within the circle centered on [ -
74, 40.74 ] and with a radius of 10:

copy
copied
db.places.find(
{ loc: { $geoWithin: { $center: [ [-74, 40.74], 10
] } } }
)

157
$centerSphere
On this page

 Definition
 Behavior
 Example

Definition

$centerSphere

Defines a circle for a geospatial query that uses spherical


geometry. The query returns documents that are within the
bounds of the circle. You can use the $centerSphere operator
on both GeoJSON objects and legacy coordinate pairs.

To use $centerSphere, specify an array that contains:

 The grid coordinates of the circle’s center point, and


 The circle’s radius measured in radians. To calculate
radians, see Calculate Distance Using Spherical Geometry.

copy
copied
{
<location field>: {
$geoWithin: { $centerSphere: [ [ <x>, <y> ],
<radius> ] }
}
}

IMPORTANT
If you use longitude and latitude, specify longitude first.

Behavior
158
Applications can use $centerSphere without having a geospatial
index. However, geospatial indexes support much faster queries
than the unindexed equivalents.

Both 2dsphere and 2d geospatial indexes


support $centerSphere.

Example

The following example queries grid coordinates and returns all


documents within a 10 mile radius of longitude 88 W and
latitude 30 N. The query converts the distance to radians by
dividing by the approximate equatorial radius of the earth, 3963.2
miles:

copy
copied
db.places.find( {
loc: { $geoWithin: { $centerSphere: [ [ -88, 30 ],
10/3963.2 ] } }
} )

159
$geometry
$geometry

The $geometry operator specifies a GeoJSON geometry for use


with the following geospatial query
operators: $geoWithin, $geoIntersects, $near,
and $nearSphere. $geometry uses EPSG:4326 as the default
coordinate reference system (CRS).

To specify GeoJSON objects with the default CRS, use the


following prototype for $geometry:

copy
copied
$geometry: {
type: "<GeoJSON object type>",
coordinates: [ <coordinates> ]
}

To specify a single-ringed GeoJSON polygon with a custom


MongoDB CRS, use the following prototype (available only
for $geoWithin and $geoIntersects):

copy
copied
$geometry: {
type: "Polygon",
coordinates: [ <coordinates> ],
crs: {
type: "name",
properties: { name: "urn:x-mongodb:crs:strict
winding:EPSG:4326" }

160
}
}

The custom MongoDB coordinate reference system has a strict


counter-clockwise winding order.

IMPORTANT
If specifying latitude and longitude coordinates, list
the longitude first and then latitude:

 Valid longitude values are between -180 and 180, both


inclusive.
 Valid latitude values are between -90 and 90, both
inclusive.

161
$maxDistance
On this page

 Definition
 Example

Definition

$maxDistance

The $maxDistance operator constrains the results of a


geospatial $near or $nearSphere query to the specified
distance. The measuring units for the maximum distance are
determined by the coordinate system in use. For GeoJSON point
objects, specify the distance in meters, not radians. You must
specify a non-negative number for $maxDistance.

The 2dsphere and 2d geospatial indexes both


support $maxDistance: .

Example

The following example query returns documents with location


values that are 10 or fewer units from the point [ -74 , 40 ].

copy
copied
db.places.find( {
loc: { $near: [ -74 , 40 ], $maxDistance: 10 }
} )

MongoDB orders the results by their distance from [ -


74 , 40 ]. The operation returns the first 100 results, unless you
modify the query with the cursor.limit() method.

162
$minDistance
On this page

 Definition
 Examples

Definition

$minDistance

Filters the results of a geospatial $near or $nearSphere query


to those documents that are at least the specified distance from
the center point.

If $near or $nearSphere query specifies the center point as


a GeoJSON point, specify the distance as a non-negative
number in meters.

If $nearSphere query specifies the center point as legacy


coordinate pair, specify the distance as a non-negative number
in radians. $near can only use the 2dsphere index if the query
specifies the center point as a GeoJSON point.

Examples

Use with $near

IMPORTANT
If specifying latitude and longitude coordinates, list
the longitude first and then latitude:

 Valid longitude values are between -180 and 180, both


inclusive.
 Valid latitude values are between -90 and 90, both inclusive.

163
Consider a collection places that has a 2dsphere index.

The following example returns documents that are at


least 1000 meters from and at most 5000 meters from the
specified GeoJSON point, sorted from nearest to farthest:

copy
copied
db.places.find(
{
location:
{ $near :
{
$geometry: { type: "Point", coordinates:
[ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

Use with $nearSphere

Consider a collection places that contains documents with


a location field and has a 2dsphere index.

Then, the following example returns whose location is at


least 1000 meters from and at most 5000 meters from the
specified point, ordered from nearest to farthest:

copy
copied
db.places.find(
{
location: {

164
$nearSphere: {
$geometry: {
type : "Point",
coordinates : [ -73.9667, 40.78 ]
},
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

For an example that specifies the center point as legacy


coordinate pair, see $nearSphere

165
$polygon
On this page

 Definition
 Behavior
 Example

Definition

$polygon

Specifies a polygon for a geospatial $geoWithin query on


legacy coordinate pairs. The query returns pairs that are within
the bounds of the polygon. The operator does not query for
GeoJSON objects.

To define the polygon, specify an array of coordinate points:

copy
copied
{
<location field>: {
$geoWithin: {
$polygon: [ [ <x1> , <y1> ], [ <x2> , <y2>
], [ <x3> , <y3> ], ... ]
}
}
}

The last point is always implicitly connected to the first. You can
specify as many points, i.e. sides, as you like.

IMPORTANT
If you use longitude and latitude, specify longitude first.

166
Behavior

The $polygon operator calculates distances using flat (planar)


geometry.

Applications can use $polygon without having a geospatial index.


However, geospatial indexes support much faster queries than the
unindexed equivalents.

Only the 2d geospatial index supports the $polygon operator.

Example

The following query returns all documents that have coordinates


that exist within the polygon defined by [ 0 , 0 ], [ 3 , 6 ],
and [ 6 , 0 ]:

copy
copied
db.places.find(
{
loc: {
$geoWithin: { $polygon: [ [ 0 , 0 ], [ 3 , 6 ]
, [ 6 , 0 ] ] }
}
}
)

167
$uniqueDocs
On this page

 Definition

Definition

$uniqueDocs

Deprecated since version 2.6: Geospatial queries no longer


return duplicate results. The $uniqueDocs operator has no
impact on results.

Returns a document only once for a geospatial query even if the


document matches the query multiple times.

168
Array Query Operators
NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

Matches arrays that contain all elements specified in the


$all
query.

Selects documents if element in the array field matches


$elemMatch
all the specified $elemMatch conditions.

$size Selects documents if the array field is a specified size.

For examples on querying array fields, see:

 Query an Array
 Query an Array of Embedded Documents

169
$all
On this page

 Behavior
 Examples
 Additional Examples

$all

The $all operator selects the documents where the value of a


field is an array that contains all the specified elements. To
specify an $all expression, use the following prototype:

copy
copied
{ <field>: { $all: [ <value1> , <value2> ... ] } }

Behavior

Equivalent to $and Operation

The $all is equivalent to an $and operation of the specified values;


i.e. the following statement:

copy
copied
{ tags: { $all: [ "ssl" , "security" ] } }

is equivalent to:

copy
copied
{ $and: [ { tags: "ssl" }, { tags: "security" } ] }

170
Nested Array

When passed an array of a nested array


(e.g. [ [ "A" ] ] ), $all matches documents where the field
contains the nested array as an element
(e.g. field: [ [ "A" ], ... ]), or the field equals the nested array
(e.g. field: [ "A" ]).

For example, consider the following query [1]:

copy
copied
db.articles.find( { tags: { $all: [ [ "ssl", "securit
y" ] ] } } )

The query is equivalent to:

copy
copied
db.articles.find( { $and: [ { tags: [ "ssl", "securit
y" ] } ] } )

which is equivalent to:

copy
copied
db.articles.find( { tags: [ "ssl", "security" ] } )

As such, the $all expression matches documents where


the tags field is an array that contains the nested
array [ "ssl", "security" ] or is an array that equals the nested
array:

copy
copied
tags: [ [ "ssl", "security" ], ... ]
tags: [ "ssl", "security" ]

171
The $all expression with a single element is for illustrative purposes
since the $all expression is unnecessary if matching only a single
[1]
element. Instead, when matching a single element, a “contains”
expression (i.e. arrayField: element ) is more suitable.

Examples

The following examples use the inventory collection that contains


the documents:

copy
copied
{
_id: ObjectId("5234cc89687ea597eabee675"),
code: "xyz",
tags: [ "school", "book", "bag", "headphone", "app
liance" ],
qty: [
{ size: "S", num: 10, color: "blue" },
{ size: "M", num: 45, color: "blue" },
{ size: "L", num: 100, color: "green" }
]
}

{
_id: ObjectId("5234cc8a687ea597eabee676"),
code: "abc",
tags: [ "appliance", "school", "book" ],
qty: [
{ size: "6", num: 100, color: "green" },
{ size: "6", num: 50, color: "blue" },
{ size: "8", num: 100, color: "brown" }
]

172
}

{
_id: ObjectId("5234ccb7687ea597eabee677"),
code: "efg",
tags: [ "school", "book" ],
qty: [
{ size: "S", num: 10, color: "blue" },
{ size: "M", num: 100, color: "blue" },
{ size: "L", num: 100, color: "green" }
]
}

{
_id: ObjectId("52350353b2eff1353b349de9"),
code: "ijk",
tags: [ "electronics", "school" ],
qty: [
{ size: "M", num: 100, color: "green" }
]
}

Use $all to Match Values

The following operation uses the $all operator to query


the inventory collection for documents where the value of
the tags field is an array whose elements include appliance, school,
and book:

copy
copied
db.inventory.find( { tags: { $all: [ "appliance", "sc
hool", "book" ] } } )

The above query returns the following documents:

173
copy
copied
{
_id: ObjectId("5234cc89687ea597eabee675"),
code: "xyz",
tags: [ "school", "book", "bag", "headphone", "app
liance" ],
qty: [
{ size: "S", num: 10, color: "blue" },
{ size: "M", num: 45, color: "blue" },
{ size: "L", num: 100, color: "green" }
]
}

{
_id: ObjectId("5234cc8a687ea597eabee676"),
code: "abc",
tags: [ "appliance", "school", "book" ],
qty: [
{ size: "6", num: 100, color: "green" },
{ size: "6", num: 50, color: "blue" },
{ size: "8", num: 100, color: "brown" }
]
}

Use $all with $elemMatch

If the field contains an array of documents, you can use


the $all with the $elemMatch operator.

The following operation queries the inventory collection for


documents where the value of the qty field is an array whose
elements match the $elemMatch criteria:

copy
copied

174
db.inventory.find( {
qty: { $all: [
{ "$elemMatch" :
{ size: "M", num: { $gt: 50} } },
{ "$elemMatch" :
{ num : 100, color: "green" } }
] }
} )

The query returns the following documents:

copy
copied
{
"_id" : ObjectId("5234ccb7687ea597eabee677"),
"code" : "efg",
"tags" : [ "school", "book"],
"qty" : [
{ "size" : "S", "num" : 10, "color" : "b
lue" },
{ "size" : "M", "num" : 100, "color" : "
blue" },
{ "size" : "L", "num" : 100, "color" : "
green" }
]
}

{
"_id" : ObjectId("52350353b2eff1353b349de9"),
"code" : "ijk",
"tags" : [ "electronics", "school" ],
"qty" : [
{ "size" : "M", "num" : 100, "color" : "
green" }
]
}

175
The $all operator exists to support queries on arrays. But you may
use the $all operator to select against a non-array field, as in the
following example:

copy
copied
db.inventory.find( { "qty.num": { $all: [ 50 ] } } )

However, use the following form to express the same query:

copy
copied
db.inventory.find( { "qty.num" : 50 } )

Both queries will select all documents in the inventory collection


where the value of the num field equals 50.

NOTE
In most cases, MongoDB does not treat arrays as sets. This
operator provides a notable exception to this approach.

Additional Examples

For additional examples in querying arrays, see:

 Query an Array
 Query an Array of Embedded Documents

For additional examples in querying, see:

 Query Documents

SEE ALSO
db.collection.find()

176
$elemMatch (query)
On this page

 Definition
 Behavior
 Examples
 Additional Examples

SEE ALSO
$elemMatch (projection)

Definition

$elemMatch

The $elemMatch operator matches documents that contain an


array field with at least one element that matches all the
specified query criteria.

copy
copied
{ <field>: { $elemMatch: { <query1>, <query2>, ...
} } }

If you specify only a single <query> condition in


the $elemMatch expression, and are not using
the $not or $ne operators inside
of $elemMatch, $elemMatch can be omitted. See Single Query
Condition.

Behavior

 You cannot specify a $where expression in an $elemMatch.


 You cannot specify a $text query expression in an $elemMatch.

177
Examples

Element Match

Given the following documents in the scores collection:

copy
copied
{ _id: 1, results: [ 82, 85, 88 ] }
{ _id: 2, results: [ 75, 88, 89 ] }

The following query matches only those documents where


the results array contains at least one element that is both
greater than or equal to 80 and is less than 85:

copy
copied
db.scores.find(
{ results: { $elemMatch: { $gte: 80, $lt: 85 } } }
)

The query returns the following document since the element 82 is


both greater than or equal to 80 and is less than 85:

copy
copied
{ "_id" : 1, "results" : [ 82, 85, 88 ] }

For more information on specifying multiple criteria on array


elements, see Specify Multiple Conditions for Array Elements.

Array of Embedded Documents

This statement inserts documents into the survey collection:

copy
copied

178
db.survey.insertMany( [
{ "_id": 1, "results": [ { "product": "abc", "scor
e": 10 },
{ "product": "xyz", "scor
e": 5 } ] },
{ "_id": 2, "results": [ { "product": "abc", "scor
e": 8 },
{ "product": "xyz", "scor
e": 7 } ] },
{ "_id": 3, "results": [ { "product": "abc", "scor
e": 7 },
{ "product": "xyz", "scor
e": 8 } ] },
{ "_id": 4, "results": [ { "product": "abc", "scor
e": 7 },
{ "product": "def", "scor
e": 8 } ] }
] )

The following query matches only those documents where


the results array contains at least one element with
both product equal to "xyz" and score greater than or equal
to 8:

copy
copied
db.survey.find(
{ results: { $elemMatch: { product: "xyz", score:
{ $gte: 8 } } } }
)

Specifically, the query matches the following document:

{ "_id" : 3, "results" : [ { "product" : "abc", "scor


e" : 7 },

179
{ "product" : "xyz", "scor
e" : 8 } ] }

Single Query Condition

If you specify a single query predicate in


the $elemMatch expression, and are not using
the $not or $ne operators inside of $elemMatch, $elemMatch can
be omitted.

The following examples return the same documents.

With $elemMatch:

copy
copied
db.survey.find(
{ results: { $elemMatch: { product: "xyz" } } }
)

Without $elemMatch:

copy
copied
db.survey.find(
{ "results.product": "xyz" }
)

However, if your $elemMatch expression contains


the $not or $ne operators then omitting
the $elemMatch expression changes the documents returned.

The following examples return different documents.

With $elemMatch:

copy
180
copied
db.survey.find(
{ "results": { $elemMatch: { product: { $ne: "xyz"
} } } }
)

Without $elemMatch:

copy
copied
db.survey.find(
{ "results.product": { $ne: "xyz" } }
)

With $elemMatch, the first query returns these documents:

{ "_id" : 1, "results" : [ { "product" : "abc", "scor


e" : 10 },
{ "product" : "xyz", "scor
e" : 5 } ] }
{ "_id" : 2, "results" : [ { "product" : "abc", "scor
e" : 8 },
{ "product" : "xyz", "scor
e" : 7 } ] }
{ "_id" : 3, "results" : [ { "product" : "abc", "scor
e" : 7 },
{ "product" : "xyz", "scor
e" : 8 } ] }
{ "_id" : 4, "results" : [ { "product" : "abc", "scor
e" : 7 },
{ "product" : "def", "scor
e" : 8 } ] }

Without $elemMatch, the second query returns this document:

181
{ "_id" : 4, "results" : [ { "product" : "abc", "scor
e" : 7 },
{ "product" : "def", "scor
e" : 8 } ] }

The first query returns the documents where any product in


the results array is not "xyz". The second query returns the
documents where all of the products in the results array are
not "xyz".

Additional Examples

For additional examples in querying arrays, see:

 Query an Array
 Query an Array of Embedded Documents

For additional examples in querying, see:

 Query Documents

SEE ALSO
db.collection.find()

182
$size
On this page

 Additional Examples

$size

The $size operator matches any array with the number of


elements specified by the argument. For example:

copy
copied
db.collection.find( { field: { $size: 2 } } );

returns all documents in collection where field is an array


with 2 elements. For instance, the above expression will
return { field: [ red, green ] } and { field: [ apple,
lime ] } but not { field: fruit } or { field: [ orange
, lemon, grapefruit ] }. To match fields with only one
element within an array use $size with a value of 1, as follows:

copy
copied
db.collection.find( { field: { $size: 1 } } );

$size does not accept ranges of values. To select documents


based on fields with different numbers of elements, create a
counter field that you increment when you add elements to a
field.

Queries cannot use indexes for the $size portion of a query,


although the other portions of a query can use indexes if
applicable.

183
Additional Examples

For additional examples in querying arrays, see:

 Query an Array
 Query an Array of Embedded Documents

For additional examples in querying, see:

 Query Documents

SEE ALSO
db.collection.find()

184
Bitwise Query Operators
NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

Matches numeric or binary values in which a set of


$bitsAllClear
bit positions all have a value of 0.

Matches numeric or binary values in which a set of


$bitsAllSet
bit positions all have a value of 1.

Matches numeric or binary values in which any bit


$bitsAnyClear
from a set of bit positions has a value of 0.

Matches numeric or binary values in which any bit


$bitsAnySet
from a set of bit positions has a value of 1.

185
$bitsAllClear
On this page

 Behavior
 Examples

$bitsAllClear

New in version 3.2.

$bitsAllClear matches documents where all of the bit


positions given by the query are clear (i.e. 0) in field.

{ <field>: { $bitsAllClear: <numeric bitmask> } }

{ <field>: { $bitsAllClear: < BinData bitmask> } }

{ <field>: { $bitsAllClear: [ <position1>, <positio


n2>, ... ] } }

The field value must be either numeric or a BinData instance.


Otherwise, $bitsAllClear will not match the current
document.

Numeric Bitmask

186
You can provide a numeric bitmask to be matched against the
operand field. It must be representable as a non-negative 32-bit
signed integer. Otherwise, $bitsAllClear will return an error.
BinData Bitmask
You can also use an arbitrarily large BinData instance as a
bitmask.
Position List
If querying a list of bit positions, each <position> must be a
non-negative integer. Bit positions start at 0 from the least
significant bit. For example, the decimal number 254 would have
the following bit positions:

Bit Value 1 1 1 1 1 1 1 0

Position 7 6 5 4 3 2 1 0

Behavior

Indexes

Queries cannot use indexes for the $bitsAllClear portion of a


query, although the other portions of a query can use indexes, if
applicable.

Floating Point Values

$bitsAllClear will not match numerical values that cannot be


represented as a signed 64-bit integer. This can be the case if a
value is either too large or too small to fit in a signed 64-bit
integer, or if it has a fractional component.

Sign Extension
187
Numbers are sign extended. For
example, $bitsAllClear considers bit position 200 to be set for
the negative number -5, but bit position 200 to be clear for the
positive number +5.

In contrast, BinData instances are zero-extended. For example,


given the following document:

copy
copied
db.collection.save({ x: BinData(0, "ww=="), binaryVal
ueofA: "11000011" })

$bitsAllClear will consider all bits outside of x to be clear.

Examples

The following examples will use a collection with the following


documents:

copy
copied
db.collection.save({ _id: 1, a: 54, binaryValueofA: "
00110110" })
db.collection.save({ _id: 2, a: 20, binaryValueofA: "
00010100" })
db.collection.save({ _id: 3, a: 20.0, binaryValueofA:
"00010100" })
db.collection.save({ _id: 4, a: BinData(0, "Zg=="), b
inaryValueofA: "01100110" })

Bit Position Array

The following query uses the $bitsAllClear operator to test


whether field a has bits clear at position 1 and position 5, where
the least significant bit is position 0.

188
copy
copied
db.collection.find( { a: { $bitsAllClear: [ 1, 5 ] }
} )

The query matches the following documents:

copy
copied
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20, "binaryValueofA" : "00010100"
}

Integer Bitmask

The following query uses the $bitsAllClear operator to test


whether field a has bits clear at positions 0, 1, and 5 (the binary
representation of the bitmask 35 is 00100011).

copy
copied
db.collection.find( { a: { $bitsAllClear: 35 } } )

The query matches the following documents:

copy
copied
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20, "binaryValueofA" : "00010100"
}

BinData Bitmask

189
The following query uses the $bitsAllClear operator to test
whether field a has bits clear at positions 2 and 4 (the binary
representation of BinData(0, "ID==") is 00010100.

copy
copied
db.collection.find( { a: { $bitsAllClear: BinData(0,
"ID==") } } )

The query matches the following documents:

copy
copied
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20, "binaryValueofA" : "00010100"
}

190
$bitsAllSet
On this page

 Behavior
 Examples

$bitsAllSet

New in version 3.2.

$bitsAllSet matches documents where all of the bit positions


given by the query are set (i.e. 1) in field.

{ <field>: { $bitsAllSet: <numeric bitmask> } }

{ <field>: { $bitsAllSet: < BinData bitmask> } }

{ <field>: { $bitsAllSet: [ <position1>, <position2


>, ... ] } }

The field value must be either numeric or a BinData instance.


Otherwise, $bitsAllSet will not match the current document.

Numeric Bitmask

191
You can provide a numeric bitmask to be matched against the
operand field. It must be representable as a non-negative 32-bit
signed integer. Otherwise, $bitsAllSet will return an error.
BinData Bitmask
You can also use an arbitrarily large BinData instance as a
bitmask.
Position List
If querying a list of bit positions, each <position> must be a
non-negative integer. Bit positions start at 0 from the least
significant bit. For example, the decimal number 254 would have
the following bit positions:

Bit Value 1 1 1 1 1 1 1 0

Position 7 6 5 4 3 2 1 0

Behavior

Indexes

Queries cannot use indexes for the $bitsAllSet portion of a


query, although the other portions of a query can use indexes, if
applicable.

Floating Point Values

$bitsAllSet will not match numerical values that cannot be


represented as a signed 64-bit integer. This can be the case if a
value is either too large or too small to fit in a signed 64-bit
integer, or if it has a fractional component.

Sign Extension
192
Numbers are sign extended. For example, $bitsAllSet considers
bit position 200 to be set for the negative number -5, but bit
position 200 to be clear for the positive number +5.

In contrast, BinData instances are zero-extended. For example,


given the following document:

copy
copied
db.collection.save({ x: BinData(0, "ww=="), binaryVal
ueofA: "11000011" })

$bitsAllSet will consider all bits outside of x to be clear.

Examples

The following examples will use a collection with the following


documents:

copy
copied
db.collection.save({ _id: 1, a: 54, binaryValueofA: "
00110110" })
db.collection.save({ _id: 2, a: 20, binaryValueofA: "
00010100" })
db.collection.save({ _id: 3, a: 20.0, binaryValueofA:
"00010100" })
db.collection.save({ _id: 4, a: BinData(0, "Zg=="), b
inaryValueofA: "01100110" })

Bit Position Array

The following query uses the $bitsAllSet operator to test


whether field a has bits set at position 1 and position 5, where the
least significant bit is position 0.

copy
193
copied
db.collection.find( { a: { $bitsAllSet: [ 1, 5 ] } }
)

The query matches the following documents:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

Integer Bitmask

The following query uses the $bitsAllSet operator to test


whether field a has bits set at positions 1, 4, and 5 (the binary
representation of the bitmask 50 is 00110010).

copy
copied
db.collection.find( { a: { $bitsAllSet: 50 } } )

The query matches the following document:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}

BinData Bitmask

The following query uses the $bitsAllSet operator to test


whether field a has bits set at positions 4 and 5 (the binary
representation of BinData(0, "MC==") is 00110000).

copy
194
copied
db.collection.find( { a: { $bitsAllSet: BinData(0, "M
C==") } } )

The query matches the following document:

copy
copied
{ _id: 1, a: 54, binaryValueofA: "00110110" }

195
$bitsAnyClear
On this page

 Behavior
 Examples

$bitsAnyClear

New in version 3.2.

$bitsAnyClear matches documents where any of the bit


positions given by the query are clear (i.e. 0) in field.

{ <field>: { $bitsAnyClear: <numeric bitmask> } }

{ <field>: { $bitsAnyClear: < BinData bitmask> } }

{ <field>: { $bitsAnyClear: [ <position1>, <positio


n2>, ... ] } }

The field value must be either numeric or a BinData instance.


Otherwise, $bitsAnyClear will not match the current
document.

Numeric Bitmask

196
You can provide a numeric bitmask to be matched against the
operand field. It must be representable as a non-negative 32-bit
signed integer. Otherwise, $bitsAnyClear will return an error.
BinData Bitmask
You can also use an arbitrarily large BinData instance as a
bitmask.
Position List
If querying a list of bit positions, each <position> must be a
non-negative integer. Bit positions start at 0 from the least
significant bit. For example, the decimal number 254 would have
the following bit positions:

Bit Value 1 1 1 1 1 1 1 0

Position 7 6 5 4 3 2 1 0

Behavior

Indexes

Queries cannot use indexes for the $bitsAnyClear portion of a


query, although the other portions of a query can use indexes, if
applicable.

Floating Point Values

$bitsAnyClear will not match numerical values that cannot be


represented as a signed 64-bit integer. This can be the case if a
value is either too large or too small to fit in a signed 64-bit
integer, or if it has a fractional component.

Sign Extension
197
Numbers are sign extended. For
example, $bitsAnyClear considers bit position 200 to be set for
the negative number -5, but bit position 200 to be clear for the
positive number +5.

In contrast, BinData instances are zero-extended. For example,


given the following document:

copy
copied
db.collection.save({ x: BinData(0, "ww=="), binaryVal
ueofA: "11000011" })

$bitsAnyClear will consider all bits outside of x to be clear.

Examples

The following examples will use a collection with the following


documents:

copy
copied
db.collection.save({ _id: 1, a: 54, binaryValueofA: "
00110110" })
db.collection.save({ _id: 2, a: 20, binaryValueofA: "
00010100" })
db.collection.save({ _id: 3, a: 20.0, binaryValueofA:
"00010100" })
db.collection.save({ _id: 4, a: BinData(0, "Zg=="), b
inaryValueofA: "01100110" })

Bit Position Array

The following query uses the $bitsAnyClear operator to test


whether field a has either bit position 1 or bit position 5 clear,
where the least significant bit is position 0.

198
copy
copied
db.collection.find( { a: { $bitsAnyClear: [ 1, 5 ] }
} )

The query matches the following documents:

copy
copied
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20.0, "binaryValueofA" : "00010100
" }

Integer Bitmask

The following query uses the $bitsAnyClear operator to test


whether field a has any bits clear at positions 0, 1, and 5 (the
binary representation of the bitmask 35 is 00100011).

copy
copied
db.collection.find( { a: { $bitsAnyClear: 35 } } )

The query matches the following documents:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20.0, "binaryValueofA" : "00010100
" }
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

199
BinData Bitmask

The following query uses the $bitsAnyClear operator to test


whether field a has any bits clear at positions 4 and 5 (the binary
representation of BinData(0, "MC==") is 00110000).

copy
copied
db.collection.find( { a: { $bitsAnyClear: BinData(0,
"MC==") } } )

The query matches the following documents:

copy
copied
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20.0, "binaryValueofA" : "00010100
" }
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

200
$bitsAnySet
On this page

 Behavior
 Examples

$bitsAnySet

New in version 3.2.

$bitsAnySet matches documents where any of the bit


positions given by the query are set (i.e. 1) in field.

{ <field>: { $bitsAnySet: <numeric bitmask> } }

{ <field>: { $bitsAnySet: < BinData bitmask> } }

{ <field>: { $bitsAnySet: [ <position1>, <position2


>, ... ] } }

The field value must be either numeric or a BinData instance.


Otherwise, $bitsAnySet will not match the current document.

Numeric Bitmask

201
You can provide a numeric bitmask to be matched against the
operand field. It must be representable as a non-negative 32-bit
signed integer. Otherwise, $bitsAnySet will return an error.
BinData Bitmask
You can also use an arbitrarily large BinData instance as a
bitmask.
Position List
If querying a list of bit positions, each <position> must be a
non-negative integer. Bit positions start at 0 from the least
significant bit. For example, the decimal number 254 would have
the following bit positions:

Bit Value 1 1 1 1 1 1 1 0

Position 7 6 5 4 3 2 1 0

Behavior

Indexes

Queries cannot use indexes for the $bitsAnySet portion of a


query, although the other portions of a query can use indexes, if
applicable.

Floating Point Values

$bitsAnySet will not match numerical values that cannot be


represented as a signed 64-bit integer. This can be the case if a
value is either too large or too small to fit in a signed 64-bit
integer, or if it has a fractional component.

Sign Extension
202
Numbers are sign extended. For example, $bitsAnySet considers
bit position 200 to be set for the negative number -5, but bit
position 200 to be clear for the positive number +5.

In contrast, BinData instances are zero-extended. For example,


given the following document:

copy
copied
db.collection.save({ x: BinData(0, "ww=="), binaryVal
ueofA: "11000011" })

$bitsAnySet will consider all bits outside of x to be clear.

Examples

The following examples will use a collection with the following


documents:

copy
copied
db.collection.save({ _id: 1, a: 54, binaryValueofA: "
00110110" })
db.collection.save({ _id: 2, a: 20, binaryValueofA: "
00010100" })
db.collection.save({ _id: 3, a: 20.0, binaryValueofA:
"00010100" })
db.collection.save({ _id: 4, a: BinData(0, "Zg=="), b
inaryValueofA: "01100110" })

Bit Position Array

The following query uses the $bitsAnySet operator to test


whether field a has either bit position 1 or bit position 5 set, where
the least significant bit is position 0.

copy
203
copied
db.collection.find( { a: { $bitsAnySet: [ 1, 5 ] } }
)

The query matches the following documents:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

Integer Bitmask

The following query uses the $bitsAnySet operator to test


whether field a has any bits set at positions 0, 1, and 5 (the binary
representation of the bitmask 35 is 00100011).

copy
copied
db.collection.find( { a: { $bitsAnySet: 35 } } )

The query matches the following documents:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

BinData Bitmask

The following query uses the $bitsAnySet operator to test


whether field a has any bits set at positions 4, and 5 (the binary
representation of BinData(0, "MC==") is 00110000).
204
copy
copied
db.collection.find( { a: { $bitsAnySet: BinData(0, "M
C==") } } )

The query matches the following documents:

copy
copied
{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110"
}
{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100"
}
{ "_id" : 3, "a" : 20.0, "binaryValueofA" : "00010100
" }
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA
" : "01100110" }

205
$comment
On this page

 Definition
 Behavior
 Examples

Definition

$comment

The $comment query operator associates a comment to any


expression taking a query predicate.

Because comments propagate to the profile log, adding a


comment can make your profile data easier to interpret and
trace.

The $comment operator has the form:

copy
copied
db.collection.find( { <query>, $comment: <comment>
} )

Behavior

You can use the $comment with any expression taking a query
predicate, such as the query predicate
in db.collection.update() or in the $match stage of
the aggregation pipeline. For an example, see Attach a Comment
to an Aggregation Expression.

206
Examples

Attach a Comment to find

The following example adds a $comment to a find() operation:

copy
copied
db.records.find(
{
x: { $mod: [ 2, 0 ] },
$comment: "Find even values."
}
)

If the Database Profiler is enabled, the following output shows the


comment in the system.profile collection:

{
"op" : "query",
"ns" : "test.records",
"command" : {
"find" : "records",
"filter" : {
"x" : {
"$mod" : [
2,
0
]
},
"$comment" : "Find even values."
},
"comment" : "Find even values.",
...

207
Comments also appear in the MongoDB log if the database profiler
level is set to 2 and slowms is set to 0ms.
This db.setProfilingLevel() command sets these two
parameters:

copy
copied
db.setProfilingLevel(2, 0)

The comment for the previous db.records.find() example then


appears as follows in the MongoDB log:

{"t":{"$date":"2020-09-17T11:32:20.415-07:00"},"s":"I
",
"c":"COMMAND", "id":51803, "ctx":"conn7","msg":"Sl
ow query",
"attr":{"type":"command","ns":"test.records","appName
":"MongoDB
Shell","command":{"find":"records","filter":{"x":{"$m
od":[2.0,0.0]},
"$comment":"Find even values."},"comment":"Find even
values."
...

Attach a Comment to an Aggregation Expression

You can use the $comment with any expression taking a query
predicate.

The following example uses the $comment operator in


the $match stage to clarify the operation:

copy
copied
db.records.aggregate( [
{ $match: { x: { $gt: 0 }, $comment: "Don't allow
negative inputs." } },
208
{ $group : { _id: { $mod: [ "$x", 2 ] }, total: {
$sum: "$x" } } }
] )

209
Projection Operators
NOTE
find() operations on views do not support the
following projection operators:

 $
 $elemMatch
 $slice
 $meta

NOTE
For details on specific operator, including syntax and examples, click
on the specific operator to go to its reference page.

Name Description

Projects the first element in an array that matches the


$
query condition.

Projects the first element in an array that matches the


$elemMatch
specified $elemMatch condition.

$meta Projects the available per-document metadata.

210
Name Description

Limits the number of elements projected from an array.


$slice
Supports skip and limit slices.

211
$ (projection)
On this page

 Definition
 Usage Considerations
 Behavior
 Examples
 Further Reading

Definition

The positional $ operator limits the contents of an <array> to


return either:

 The first element that matches the query condition on the


array.
 The first element if no query condition is specified for the
array (Starting in MongoDB 4.4).

Use $ in the projection document of the find() method or


the findOne() method when you only need one particular array
element in selected documents.

See the aggregation operator $filter to return an array with


only those elements that match the specified condition.

DISAMBIGUATION
To specify an array element to update, see the positional $
operator for updates.

Usage Considerations
212
Both the $ operator and the $elemMatch operator project
the first matching element from an array based on a condition.

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

The $elemMatch projection operator takes an explicit condition


argument. This allows you to project based on a condition not in
the query, or if 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

Syntax

To return the first array element that matches the specified query
condition on the array:

copy
copied
db.collection.find( { <array>: <condition> ... },
{ "<array>.$": 1 } )
db.collection.find( { <array.field>: <condition> ...}
,
{ "<array>.$": 1 } )

Changed in version 4.4: You can use the $ operator to limit


an <array> field which does not appear in the query document. In
previous versions of MongoDB, the <array> field being
limited must appear in the query document.

copy

213
copied
db.collection.find( { <someOtherArray>: <condition> .
.. },
{ "<array>.$" : 1 } )

IMPORTANT
To ensure expected behavior, the arrays used in the query
document and the projection document must be the same length.
If the arrays are different lenghts, the operation may error in
certain scenarios.

Array Field Limitations

MongoDB requires the following when dealing with projection over


arrays:

 Only one positional $ operator may appear in the projection


document.
 Only one array field should appear in the query document.
Additional array fields in the query document may lead to
undefined behavior.
For example, the following projection may lead to undefined
behavior:

copy

copied

db.collection.find( { <array>: <value>, <someOth


erArray>: <value2> },
{ "<array>.$": 1 } )
 The query document should only contain a single condition
on the array field to which it is applied. Multiple conditions
may override each other internally and lead to undefined
behavior.
To specify criteria on multiple fields of documents inside that
array, use the $elemMatch query operator. The following

214
query returns the first document inside a grades array that
has a mean of greater than 70 and a grade of greater than 90.

copy

copied

db.students.find( { grades: { $elemMatch: {


mean
: { $gt: 70 },
grad
e: { $gt:90 }
} } },
{ "grades.$": 1 } )
You must use the $elemMatch operator if you need separate
conditions for selecting documents and for choosing fields
within those documents.

Sorts and the Positional Operator

When the find() method includes a sort(), the find() method


applies the sort() to order the matching documents before it
applies the positional $ projection operator.

If an array field contains multiple documents with the same field


name and the find() method includes a sort() on that repeating
field, the returned documents may not reflect the sort order
because the sort was applied to the elements of the array before
the $ projection operator.

Positional Operator Placement Restriction

Starting in MongoDB 4.4, the $ projection operator can only


appear at the end of the field path;
e.g. "field.$" or "fieldA.fieldB.$".

215
For example, starting in MongoDB 4.4, the following operation is
invalid:

db.inventory.find( { }, { "instock.$.qty": 1 } ) // I
nvalid starting in 4.4

To resolve, remove the component of the field path that follows


the $ projection operator.

In previous versions, MongoDB ignores the part of the path that


follows the $; i.e. the projection is treated as "instock.$".

Positional Operator and $slice Restriction

Starting in MongoDB 4.4, find and findAndModify projection


cannot include $slice projection expression as part of
a $ projection expression.

For example, starting in MongoDB 4.4, the following operation is


invalid:

db.inventory.find( { "instock.qty": { $gt: 25 } }, {


"instock.$": { $slice: 1 } } ) // Invalid starting in
4.4

MongoDB already has a restriction where top-level field names


cannot start with the dollar sign ($).

In previous versions, MongoDB returns the first element


(instock.$) in the instock array that matches the query
condition; i.e. the positional projection "instock.$" takes
precedence and the $slice:1 is a no-op.
The "instock.$": { $slice: 1 } does not exclude any other
document field.

Examples

216
Project Array Values

A collection students contains the following documents:

copy
copied
{ "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90
] }
{ "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92
] }
{ "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90
] }
{ "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80
] }
{ "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92
] }
{ "_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 85 for
the grades field.

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

The operation returns the following documents:

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

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

Project Array Documents

A students collection contains the following documents where


the grades field is an array of documents; each document contain
the three field names grade, mean, and std:

copy
copied
{ "_id" : 7, semester: 3, "grades" : [ { grade: 80, m
ean: 75, std: 8 },
{ grade: 85, m
ean: 90, std: 5 },
{ grade: 90, m
ean: 85, std: 3 } ] }

{ "_id" : 8, semester: 3, "grades" : [ { grade: 92, m


ean: 88, std: 8 },
{ grade: 78, m
ean: 90, std: 5 },
{ grade: 88, m
ean: 85, std: 3 } ] }

In the following query, the projection { "grades.$": 1 } returns


only the first element with the mean greater than 70 for
the grades field:

copy
copied
db.students.find(
{ "grades.mean": { $gt: 70 } },
{ "grades.$": 1 }
)

218
The operation returns the following documents:

copy
copied
{ "_id" : 7, "grades" : [ { "grade" : 80, "mean" :
75, "std" : 8 } ] }
{ "_id" : 8, "grades" : [ { "grade" : 92, "mean" :
88, "std" : 8 } ] }

219
$elemMatch (projection)
SEE ALSO
$elemMatch (query)

On this page

 Definition
 Usage Considerations
 Examples

Definition

$elemMatch

The $elemMatch operator limits the contents of


an <array> field from the query results to contain only
the first element matching the $elemMatch condition.

Usage Considerations

Returned Element

Both the $ operator and the $elemMatch operator project


the first matching element from an array based on a condition.

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

The $elemMatch projection operator takes an explicit condition


argument. This allows you to project based on a condition not in
the query, or if you need to project based on multiple fields in the
array’s embedded documents. See Array Field Limitations for an
example.

220
Field Order

Starting in MongoDB 4.4, regardless of the ordering of the fields in


the document, the $elemMatch projection of an existing field
returns the field after the other existing field inclusions.

For example, consider a players collection with the following


document:

copy
copied
db.players.insert( {
name: "player1",
games: [ { game: "abc", score: 8 }, { game: "xyz",
score: 5 } ],
joined: new Date("2020-01-01"),
lastLogin: new Date("2020-05-01")
} )

In version 4.4+, the following projection returns the games field


after the other existing fields included in the projection even
though in the document, the field is listed
before joined and lastLogin fields:

copy
copied
db.players.find( {}, { games: { $elemMatch: { score:
{ $gt: 5 } } }, joined: 1, lastLogin: 1 } )

That is, the operation returns the following document:

{
"_id" : ObjectId("5edef64a1c099fff6b033977"),
"joined" : ISODate("2020-01-01T00:00:00Z"),
"lastLogin" : ISODate("2020-05-01T00:00:00Z"),
"games" : [ { "game" : "abc", "score" : 8 } ]
}
221
In version 4.2 and earlier, the $elemMatch projection of an
existing field upholds the ordering in the document:

{
"_id" : ObjectId("5edef91e76ddff7d92f118e1"),
"games" : [ { "game" : "abc", "score" : 8 } ],
"joined" : ISODate("2020-01-01T00:00:00Z"),
"lastLogin" : ISODate("2020-05-01T00:00:00Z")
}

Restrictions

 db.collection.find() operations on views do not


support $elemMatch projection operator.
 You cannot specify a $text query expression in an $elemMatch.

Examples

The examples on the $elemMatch projection operator assumes a


collection schools with the following documents:

copy
copied
{
_id: 1,
zipcode: "63109",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
}
{
_id: 2,
zipcode: "63110",
students: [

222
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8
},
]
}
{
_id: 3,
zipcode: "63109",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8
},
]
}
{
_id: 4,
zipcode: "63109",
students: [
{ name: "barney", school: 102, age: 7 }
,
{ name: "ruth", school: 102, age: 16 },
]
}

Zipcode Search

The following find() operation queries for all documents where


the value of the zipcode field is 63109.
The $elemMatch projection returns only the first matching
element of the students array where the school field has a value
of 102:

copy
copied
db.schools.find( { zipcode: "63109" },

223
{ students: { $elemMatch: { school:
102 } } } )

The operation returns the following documents that


have zipcode equal to 63109 and projects the students array
using $elemMatch:

copy
copied
{ "_id" : 1, "students" : [ { "name" : "john", "schoo
l" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "sch
ool" : 102, "age" : 7 } ] }

 For the document with _id equal to 1, the students array


contains multiple elements with the school field equal
to 102. However, the $elemMatch projection returns only the
first matching element from the array.
 The document with _id equal to 3 does not contain
the students field in the result since no element in
its students array matched the $elemMatch condition.

$elemMatch with Multiple Fields

The $elemMatch projection can specify criteria on multiple fields:

The following find() operation queries for all documents where


the value of the zipcode field is 63109. The projection includes
the first matching element of the students array where
the school field has a value of 102 and the age field is greater
than 10:

copy
copied
db.schools.find( { zipcode: "63109" },

224
{ students: { $elemMatch: { school:
102, age: { $gt: 10} } } } )

The operation returns the three documents that


have zipcode equal to 63109:

copy
copied
{ "_id" : 1, "students" : [ { "name" : "jess", "schoo
l" : 102, "age" : 11 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "ruth", "schoo
l" : 102, "age" : 16 } ] }

The document with _id equal to 3 does not contain


the students field since no array element matched
the $elemMatch criteria.

SEE ALSO
$ (projection) operator

225
$slice (projection)
On this page

 Definition
 Syntax
 Behavior
 Examples

Definition

$slice

The $slice projection operator specifies the number of


elements in an array to return in the query result.

DISAMBIGUATION
For information on limiting the size of an array during an update
with $push, see the $slice modifier instead.
For aggregation operator, see $slice aggregation operator
instead.

Syntax

The $slice has one of the following syntax forms:

copy
copied
db.collection.find(
<query>,
{ <arrayField>: { $slice: <number> } }
);

or

226
copy
copied
db.collection.find(
<query>,
{ <arrayField>: { $slice: [ <number>, <number> ] }
}
);

Value Description

Specifies the number


of elements to return
in
the <arrayField>.
For <number>:

 Specify a
positive
number n to
return the
$slice: <number> first n elements.
 Specify a
negative
number n to
return the
last n elements.

If the <number> is
greater than the
number of array
elements, the query
returns all array

227
Value Description

elements.

Specifies the number


of elements to return
in
the <arrayField> a
fter skipping the
specified number of
elements starting
from the first
element. You must
specify both elements.

For
$slice: [ <number to skip>, <number the <number to sk
to return> ] ip>:

 Specify a
positive
number n to
skip n elements
from the start
of the array; i.e.
0th index
position. Based
on a zero-based
array
index, 1 indicat
es the starting

228
Value Description

position of the
2nd element,
etc. If n is
greater than the
number of
array elements,
the query
returns an
empty array for
the <arrayFi
eld>.
 Specify a
negative
number n to
skip
backward n ele
ments from the
start of the
array; i.e. 0th
index position
Based on a
zero-based
array index (i.e.
the first element
is at index 0), -
1 indicates the
starting
position of the
last element,
etc. If the
absolute value

229
Value Description

of the negative
number is
greater than the
number of
array elements,
the starting
position is the
start of the
array.

For
the <number to re
turn>, you must
specify
a positive number n to
return the
next n elements,
starting after
skipping the specified
number.

Behavior

$slice of Embedded Array

Starting in MongoDB 4.4, the $slice projection of an array in an


nested document no longer returns the other fields in the nested
document when the projection is part of an inclusion projection.

230
For example, consider a collection inventory with documents
that contain a size field:

{ item: "socks", qty: 100, details: { colors: [ "blue


", "red" ], sizes: [ "S", "M", "L"] } }

Starting in MongoDB 4.4, the following operation projects


the _id field (by default), the qty field, and the details field with
just the specified slice of the colors array:

copy
copied
db.inventory.find( { }, { qty: 1, "details.colors": {
$slice: 1 } } )

That is, the operation returns the following document:

{ "_id" : ObjectId("5ee92a6ec644acb6d13eedb1"), "qty"


: 100, "details" : { "colors" : [ "blue" ] } }

If the $slice projection is part of an exclusion projection, the


operation continues to return the other fields in the nested
document. That is, the following projection is an exclusion
projection. The projection excludes the _id field and the elements
in the colors array that fall outside the specified slice and returns
all other fields.

copy
copied
db.inventory.find( { }, { _id: 0, "details.colors": {
$slice: 1 } } )
{ "item" : "socks", "qty" : 100, "details" : { "color
s" : [ "blue" ], "sizes" : [ "S", "M", "L" ] } }

The $slice projection by itself is considered an exclusion.

231
In previous versions, the $slice projection also include the other
fields in the nested document regardless of whether the projection
is an inclusion or an exclusion.

View Restriction

db.collection.find() operations on views do not


support $slice projection operator.

$ Positional Operator and $slice Restriction

Starting in MongoDB 4.4, find and findAndModify projection


cannot include $slice projection expression as part of
a $ projection expression.

For example, starting in MongoDB 4.4, the following operation is


invalid:

db.inventory.find( { "instock.qty": { $gt: 25 } }, {


"instock.$": { $slice: 1 } } ) // Invalid starting in
4.4

MongoDB already has a restriction where top-level field names


cannot start with the dollar sign ($).

In previous versions, MongoDB returns the first element


(instock.$) in the instock array that matches the query
condition; i.e. the positional projection "instock.$" takes
precedence and the $slice:1 is a no-op.
The "instock.$": { $slice: 1 } does not exclude any other
document field.

Path Collision: $slice of an Array and Embedded Fields

Starting in MongoDB 4.4, find and findAndModify projection


cannot contain both a $slice of an array and a field embedded in
the array.
232
For example, consider a collection inventory that contains an
array field instock:

{ ..., instock: [ { warehouse: "A", qty: 35 }, { ware


house: "B", qty: 15 }, { warehouse: "C", qty: 35 } ],
... }

Starting in MongoDB 4.4, the following operation fails with


a Path collision error:

db.inventory.find( {}, { "instock": { $slice: 1 }, "i


nstock.warehouse": 0 } ) // Invalid starting in 4.4

In previous versions, the projection applies both projections and


returns the first element ($slice: 1) in the instock array but
suppresses the warehouse field in the projected element. Starting
in MongoDB 4.4, to achieve the same result, use
the db.collection.aggregate() method with two
separate $project stages.

SEE ALSO
Projection

Examples

Create an example collection posts with the following documents:

copy
copied
db.posts.insertMany([
{
_id: 1,
title: "Bagels are not croissants.",
comments: [ { comment: "0. true" }, { comment: "
1. croissants aren't bagels."} ]
},

233
{
_id: 2,
title: "Coffee please.",
comments: [ { comment: "0. fooey" }, { comment:
"1. tea please" }, { comment: "2. iced coffee" }, { c
omment: "3. cappuccino" }, { comment: "4. whatever" }
]
}
])

Return an Array with Its First 3 Elements

The following operation uses the $slice projection operator on


the comments array to return the array with its first three elements.
If the array has less than three elements, all elements in the array
are returned.

copy
copied
db.posts.find( {}, { comments: { $slice: 3 } } )

The operation returns the following documents:

copy
copied
{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "0. true" }, { "comme
nt" : "1. croissants aren't bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",

234
"comments" : [ { "comment" : "0. fooey" }, { "comm
ent" : "1. tea please" }, { "comment" : "2. iced coff
ee" } ]
}

Return an Array with Its Last 3 Elements

The following operation uses the $slice projection operator on


the comments array to return the array with its last three elements.
If the array has less than three elements, all elements in the array
are returned.

copy
copied
db.posts.find( {}, { comments: { $slice: -3 } } )

The operation returns the following documents:

copy
copied
{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "0. true" }, { "comme
nt" : "1. croissants aren't bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "2. iced coffee" }, {
"comment" : "3. cappuccino" }, { "comment" : "4. what
ever" } ]
}

Return an Array with 3 Elements After Skipping the First Element

235
The following operation uses the $slice projection operator on
the comments array to:

 Skip the first element such that the second element is the
starting point.
 Then, return three elements from the starting point.

If the array has less than three elements after the skip, all
remaining elements are returned.

copy
copied
db.posts.find( {}, { comments: { $slice: [ 1, 3 ] } }
)

The operation returns the following documents:

copy
copied
{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "1. croissants aren't
bagels." } ]
}

{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "1. tea please" }, {
"comment" : "2. iced coffee" }, { "comment" : "3. cap
puccino" } ]
}

Return an Array with 3 Elements After Skipping the Last Element

236
The following operation uses the $slice projection operator on
the comments array to

 Skip backwards from the first element such that the last
element is the starting point.
 Then, return three elements from the starting point.

If the array has less than three elements after the skip, all
remaining elements in the array are returned.

copy
copied
db.posts.find( {}, { comments: { $slice: [ -1, 3 ] }
} )

The operation returns the following documents:

copy
copied
{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "1. croissants aren't
bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "4. whatever" } ]
}

237

You might also like