[go: up one dir, main page]

0% found this document useful (0 votes)
46 views27 pages

1 - MongoDB Query Operators - 3

The document provides an overview of MongoDB query and update operators, including comparison, logical, and evaluation operators. It details various operators like $eq, $gt, $lt, $in, and their usage in querying and updating documents. Additionally, it includes examples demonstrating how to apply these operators in MongoDB queries and updates.

Uploaded by

Mani Baluchamy
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)
46 views27 pages

1 - MongoDB Query Operators - 3

The document provides an overview of MongoDB query and update operators, including comparison, logical, and evaluation operators. It details various operators like $eq, $gt, $lt, $in, and their usage in querying and updating documents. Additionally, it includes examples demonstrating how to apply these operators in MongoDB queries and updates.

Uploaded by

Mani Baluchamy
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
You are on page 1/ 27

MongoDB Query Operators

There are many query operators that can be used to compare and reference document fields.

Comparison Operators

The following operators can be used in queries to compare values:

$eq = : Values are equal


$ne != : Values are not equal
$gt > : Value is greater than another value
$gte >= : Value is greater than or equal to another value
$lt < : Value is less than another value
$lte <= : Value is less than or equal to another value
$in IN : Value is matched within an array

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 Operators

The following operators can logically compare multiple queries.

$and AND : Returns documents where both queries match


$or OR : Returns documents where either query matches
$ NOR : Returns documents where both queries fail to match
$ NOT : Returns documents where the query does not match

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

$not Inverts the effect of a query predicate and returns documents that do not match the query
predicate.

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

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

Evaluation

The following operators assist in evaluating documents.


$regex : Allows the use of regular expressions when evaluating field values
$text : Performs a text search
$where : Uses a JavaScript expression to match documents

MongoDB Update Operators

There are many update operators that can be used during document updates.

Fields

The following operators can be used to update fields:

$currentDate : Sets the field value to the current date


$inc : Increments the field value
$rename : Renames the field
$set : Sets the value of a field
$unset : Removes the field from the document

Array

The following operators assist with updating arrays.

$addToSet : Adds distinct elements to an array


$pop : Removes the first or last element of an array
$pull : Removes all elements from an array that match the query
$push : Adds an element to an array

**************************

Comparison Operators

db.inventory.insertMany( [
{ _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" ] }
])
$eq (=) - Equals a Specified Value

$eq

Specifies equality condition. The $eq operator matches documents where the value of a field
equals the specified value.

Syntax

The $eq operator has the following form:

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

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

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

The query is equivalent to:

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

Both queries match the following documents:

[
{ _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

item: { name: "cd", code: "123" }

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.

Example :

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

The query is equivalent to:

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

Both queries match the following document:


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

Example :

db.inventory.find( { "item.code": { $eq: "123"} } )

{ _id: 1, item: { name: 'ab', code: '123' }, qty: 15, tags: [ 'A', 'B', 'C' ]}
{ _id: 2, item: { name: 'cd', code: '123' }, qty: 20, tags: [ 'B' ]}

Array Element Equals a Value

tags: [ "A", "B", "C" ]

The following example queries the inventory collection to select all documents where the tags array
contains an element with the value "B" [1]:

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

The query is equivalent to:

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

Both queries match the following documents:

[
{ _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" ] }
]

Equals an Array Value

array [ "A", "B" ]

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" ].

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

The query is equivalent to:

Example :
db.inventory.find( { tags: [ "A", "B" ] } )
Both queries match the following documents:

[
{ _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" ] }
]

Regex Match Behaviour

The following examples demonstrate the differences in behavior between implicit and
explicit regular expression matching. Consider a collection with these documents:

Example :

db.companies.insertMany( [
{ _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:

db.collection.find( { company: "MongoDB" }, {_id: 0 }) or


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.

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

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:

db.companies.find( { company: /MongoDB/ }, {_id: 0 }) or


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

return the same results:

[
{ company: "MongoDB" },
{ company: "MongoDB2" }
]

$gt (>)

$gt selects those documents where the value of the specified field is greater than (i.e. >) the
specified value.

Syntax

The $gt operator has the following form:

{ field: { $gt: value } }

db.inventory.insertMany( [
{
"item": "nuts", "quantity": 30,
"carrier": { "name": "Shipit", "fee": 3 }
},
{
"item": "bolts", "quantity": 50,
"carrier": { "name": "Shipit", "fee": 4 }
},
{
"item": "washers", "quantity": 10,
"carrier": { "name": "Shipit", "fee": 1 }
}
])

Match Document Fields

Example :

Select all documents in the inventory collection where quantity is greater than 20:

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

Output :
{ _id: ObjectId("61ba25cbfe687fce2f042414"), item: 'nuts', quantity: 30,
carrier: { name: 'Shipit', fee: 3 }
},

{ _id: ObjectId("61ba25cbfe687fce2f042415"), item: 'bolts', quantity: 50,


carrier: { name: 'Shipit', fee: 4 }
}

Perform an Update Based on Embedded Document Fields


The following example sets the price field based on a $gt comparison against a field in an
embedded document.

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

Output :
{
{ _id: ObjectId("61ba3ec9fe687fce2f042417"), item: 'nuts', quantity: 30,
carrier: { name: 'Shipit', fee: 3 }, price: 9.99 },

{ _id: ObjectId("61ba3ec9fe687fce2f042418"), item: 'bolts', quantity: 50,


carrier: { name: 'Shipit', fee: 4 } },

{ _id: ObjectId("61ba3ec9fe687fce2f042419"), item: 'washers', quantity: 10,


carrier: { name: 'Shipit', fee: 1 }
}

$gte

$gte selects the documents where the value of the specified field is greater than or equal to
(i.e. >=) a specified value (e.g. value.)

Syntax
The $gte operator has the following form:

{ field: { $gte: value } }

db.inventory.insertMany( [
{
"item": "nuts", "quantity": 30,
"carrier": { "name": "Shipit", "fee": 3 }
},
{
"item": "bolts", "quantity": 50,
"carrier": { "name": "Shipit", "fee": 4 }
},
{
"item": "washers", "quantity": 10,
"carrier": { "name": "Shipit", "fee": 1 }
}
])

Match Document Fields

Select all documents in the inventory collection where quantity is greater than or equal to 20:

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


Example : Update
db.inventory.updateMany(
{ "carrier.fee": { $gte: 2 } }, { $set: { "price": 9.99 } }
)

$lt

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

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

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

$lte

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

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

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

$ne

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

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

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

Example : Update

db.inventory.updateMany(
{ "carrier.fee" : { $ne: 1 } },
{ $set: { "price": 9.99 } }
)

The SQL equivalent to this query is:

UPDATE INVENTORY SET PRICE = '9.99' WHERE carrierfee != 1


Arrays

db.inventory.insertMany( [
{
"item": "nuts", "quantity": 30,
"carrier": { "name": "Shipit", "fee": 3 }
},
{
"item": "bolts", "quantity": 50,
"carrier": { "name": "Shipit", "fee": 4 }
},
{
"item": "washers", "quantity": 10,
"carrier": { "name": "Shipit", "fee": 1 }
}
])

The following complete example adds a type array to two inventory documents and runs a query
with $ne:

db.inventory.find( { type: { $ne: [ "hardware", "fasteners" ] } } )

// Update the nuts document to include a type array


db.inventory.updateOne(
{ item: "nuts" },
{ $set: { type: [ "hardware" ] } }
)

// Update the bolts document to include a type array


db.inventory.updateOne(
{ item: "bolts" },
{ $set: { type: [ "hardware", "fasteners" ] } }
)

// Find documents where the type array differs from [ "hardware", "fasteners" ]
db.inventory.find( { type: { $ne: [ "hardware", "fasteners" ] } } )

The following query reverses the elements in the array:

db.inventory.find( { type: { $ne: [ "fasteners", "hardware" ] } } )

$ne matches documents where the array doesn't contain the specified value and documents that
don't have the array. For example:

db.inventory.find( { type: { $ne: "fasteners" } } )

$in

The $in operator selects the documents where the value of a field equals any value in the specified
array.
Syntax : { field: { $in: [<value1>, <value2>, ... <valueN> ] } }

Note : $in operator to tens of values. Using hundreds of parameters or more can negatively
impact query performance.

db.inventory.insertMany( [
{ "item": "Pens", "quantity": 350, "tags": [ "school", "office" ] },
{ "item": "Erasers", "quantity": 15, "tags": [ "school", "home" ] },
{ "item": "Maps", "tags": [ "office", "storage" ] },
{ "item": "Books", "quantity": 5, "tags": [ "school", "storage", "home" ] }
])

Example :

db.inventory.find( { quantity: { $in: [ 5, 15 ] } }, { _id: 0 } )

Output :
{ item: 'Erasers', quantity: 15, tags: [ 'school', 'home' ] }
{ item: 'Books', quantity: 5, tags: [ 'school', 'storage', 'home' ] }

$in - Array

db.inventory.updateMany(
{ tags: { $in: [ "home", "school" ] } },
{ $set: { exclude: false } }
)

$in - Regular Expression

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.

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

$nin

The specified field value is not in the specified array or the specified field does not exist.

Syntax : { field: { $nin: [ <value1>, <value2> ... <valueN> ] } }

db.inventory.insertMany( [
{ "item": "Pens", "quantity": 350, "tags": [ "school", "office" ] },
{ "item": "Erasers", "quantity": 15, "tags": [ "school", "home" ] },
{ "item": "Maps", "tags": [ "office", "storage" ] },
{ "item": "Books", "quantity": 5, "tags": [ "school", "storage", "home" ] }
])
db.inventory.find( { quantity: { $nin: [ 5, 15 ] } }, { _id: 0 } )

Output :

{ item: 'Pens', quantity: 350, tags: [ 'school', 'office' ] },


{ item: 'Maps', tags: [ 'office', 'storage' ] }

Select on Elements Not in an Array

Set the exclude field to true for documents that don't have the "school" tag.

db.inventory.updateMany(
{ tags: { $nin: [ "school" ] } },
{ $set: { exclude: true } }
)

Logical Operators

$and

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


(<expression1>, <expression2>, and so on) and selects the documents that satisfy all the
expressions.

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

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

Example:

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

The query selects all documents in the inventory collection where:

the price field value is not equal to 1.99 and

the price field exists.

The query can be rewritten with an implicit AND operation that combines the operator
expressions for the price field:

db.inventory.find( { price: { $ne: 1.99, $exists: true } } )

The query selects 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.
The query cannot use an implicit AND operation because it uses the $or operator more than once.

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

$or

The $or operator performs a logical OR operation on an array of one or more <expressions>
and selects the documents that satisfy at least one of the <expressions>.

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

Example : 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.

$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:

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

$not

$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.

Syntax: { field: { $not: { <operator-expression> } } }

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

Regular Expressions

For example, the following query selects all documents in the inventory collection where the
item field value does not start with the letter p.
db.inventory.find( { item: { $not: /^p.*/ } } )

$regex operator expression

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

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


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

$nor

$nor performs a logical NOR operation on an array of one or more query predicates and selects the
documents that fail all the query predicates in the array. The $nor has the following syntax:

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

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

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 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

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

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

$nor and $exists

Compare that with the following query which uses the $nor operator with the $exists
operator:

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

db.inventory.find( { $nor: [ { price: 1.99 }, { price: { $exists: false } },


{ sale: true }, { sale: { $exists: false } } ] } )

Element

$exists - Matches documents that have the specified field.

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

$exists

The $exists operator matches documents that contain or do not contain a specified field,
including documents where the field value is null.

Note : MongoDB $exists does not correspond to SQL operator exists. For SQL exists, refer to the
$in operator.

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]

Exists and Not Equal To

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 spices with the following
documents:

$exists: true
db.spices.find( { saffron: { $exists: true } } )

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

{ saffron: 5, cinnamon: 5, mustard: null }


{ saffron: 3, cinnamon: null, mustard: 8 }
{ saffron: null, cinnamon: 3, mustard: 9 }
{ saffron: 1, cinnamon: 2, mustard: 3 }
{ saffron: 2, mustard: 5 }
{ saffron: 3, cinnamon: 2 }
{ saffron: 4 }

$exists: false

The following query specifies the query predicate cinnamon: { $exists: false }:

db.spices.find( { cinnamon: { $exists: false } } )

The results consist of those documents that do not contain the field cinnamon:

{ saffron: 2, mustard: 5 }
{ saffron: 4 }
{ mustard: 6 }

$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.

Syntax
A $type expression for a single BSON type has the following syntax:

{ 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:

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

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

Type Number Alias Notes


Double 1 "double"
String 2 "string"
Object 3 "object"
Array 4 "array"
Binary data 5 "binData"
Undefined 6 "undefined" Deprecated.
ObjectId 7 "objectId"
Boolean 8 "bool"
Date 9 "date"
Null 10 "null"
Regular Expression 11 "regex"
DBPointer 12 "dbPointer" Deprecated.
JavaScript 13 "javascript"
Symbol 14 "symbol" Deprecated.
32-bit integer 16 "int"
Timestamp 17 "timestamp"
64-bit integer 18 "long"
Decimal128 19 "decimal"
Min key -1 "minKey"
Max key 127 "maxKey"

db.data.insertMany( [
{ _id : 1, x : { "$minKey" : 1 } },
{ _id : 2, y : { "$maxKey" : 1 } }
])

The following query returns the document with _id: 1:

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

The following query returns the document with _id: 2:

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

The addressBook contains addresses and zipcodes, where zipCode has string, int, double, and long
values:

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

db.addressBook.find( { zipCode : { $type : 2 } } );


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

These queries return:

{ _id : 1, address : "2030 Martian Way", zipCode : "90698345" }


{ _id : 5, address : "104 Venus Drive", zipCode : [ "834847278", "1893289032" ] }

The following queries return all documents where zipCode is the BSON type double or is an array
containing an element of the specified type:
db.addressBook.find( { zipCode : { $type : 1 } } );
db.addressBook.find( { zipCode : { $type : "double" } } );

These queries return:

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

Querying by Multiple Data Types

The grades collection contains names and averages, where classAverage has string, int, and double
values:

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" , classAverage : 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.

db.grades.find( { classAverage : { $type : [ 2 , 1 ] } } );


db.grades.find( { classAverage : { $type : [ "string" , "double" ] } } );

These queries return the following documents:

{ _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:

db.restaurants.insertOne( [
{
_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 : MinKey(), score : 30 },
{ date : new Date(1322006400000), grade : "C", score : 15 }
],
name : "Dirty Dan's Donuts",
restaurant_id : "30075445"
}
])

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

db.restaurants.insertOne( [
{
_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 : MaxKey(), score : 2 },
{ date : new Date(1378857600000), grade : "B", score : 6 },
{ date : new Date(1358985600000), grade : MaxKey(), 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:

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

This returns the following results:

{
_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"), grade : "C", score : 15 },
{ date : ISODate("2013-09-11T00:00:00Z"), grade : "C", score : 16 },
{ date : ISODate("2013-01-24T00:00:00Z"), grade : { "$minKey" : 1 }, score : 30 },
{ date : ISODate("2011-11-23T00:00:00Z"), grade : "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:

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

This returns the following results:

{
_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"), grade : { "$maxKey" : 1 }, score : 2 },
{ date : ISODate("2013-09-11T00:00:00Z"), grade : "B", score : 6 },
{ date : ISODate("2013-01-24T00:00:00Z"), grade : { "$maxKey" : 1 }, score : 3 },
{ date : ISODate("2011-11-23T00:00:00Z"), grade : "B", score : 5 }
],
name : "Dainty Daisey's Donuts",
restaurant_id : "30075449"
}

Querying by Array Type

A collection named sensorReading contains the following documents:

db.sensorReading.insertMany( [
{ _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 : [] },
{ _id : 5, readings : 24 }
])

The following query returns any document in which the readings field is an array, empty or
non-empty.

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

The above query returns the following documents:

{
_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 : []
}
In the documents with _id : 1, _id : 2, _id : 3, and _id : 4, the readings field is an array.

Evaluation

Name Description

$expr Allows use of aggregation expressions within the query language.

$jsonSchema Validate documents against the given JSON Schema.

$mod Performs a modulo operation on the value of a field and selects documents with a
specified result.

$regex Selects documents where values match a specified regular expression.

$text Performs text search.


provides text query capabilities for self-managed (non-Atlas) deployments. For data
hosted on MongoDB Atlas, MongoDB offers an improved full-text query solution,
Atlas Search.
$expr

Allows the use of expressions within a query predicate.

Syntax: { $expr: { <expression> } }

$expr in $lookup Operations

When $expr appears in a $match stage that is part of a $lookup subpipeline, $expr can refer
to let variables defined by the $lookup stage. For an example, see Use Multiple Join Conditions and
a Correlated Subquery.

The $eq, $lt, $lte, $gt, and $gte comparison operators placed in an $expr operator can use an
index on the from collection referenced in a $lookup stage. Limitations:

Indexes can only be used for comparisons between fields and constants, so the let operand
must resolve to a constant.

For example, a comparison between $a and a constant value can use an index, but a
comparison between $a and $b cannot.

Indexes are not used for comparisons where the let operand resolves to an empty or missing
value.

Multikey indexes are not used.

Compare Two Fields from a Single Document

$expr can contain expressions that compare fields from the same document.

Create a monthlyBudget collection with these documents:

spent amount exceeds the budget

db.monthlyBudget.insertMany( [
{ _id : 1, category : "food", budget : 400, spent : 450 },
{ _id : 2, category : "drinks", budget : 100, spent : 150 },
{ _id : 3, category : "clothes", budget : 100, spent : 50 },
{ _id : 4, category : "misc", budget : 500, spent : 300 },
{ _id : 5, category : "travel", budget : 200, spent : 650 }
])

The following operation uses $expr to find documents where the spent amount exceeds the budget:

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

Output:
{ _id : 1, category : "food", budget : 400, spent : 450 }
{ _id : 2, category : "drinks", budget : 100, spent : 150 }
{ _id : 5, category : "travel", budget : 200, spent : 650 }

Use $expr With Conditional Statements

Some queries require the ability to execute conditional logic when defining a query filter.
The aggregation pipeline 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:

db.supplies.insertMany( [
{ _id : 1, item : "binder", qty : NumberInt("100"), price : NumberDecimal("12") },
{ _id : 2, item : "notebook", qty : NumberInt("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 : NumberInt("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.

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"):

// Aggregation expression to calculate discounted price


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 aggregation 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).

Document Discounted Price <


NumberDecimal("5")
{"_id": 1, "item": "binder", "qty": 100, "price": NumberDecimal("12") } NumberDecimal("6.00")
false
{"_id": 2, "item": "notebook", "qty": 200, "price": NumberDecimal("8") } NumberDecimal("4.00")
true
{"_id": 3, "item": "pencil", "qty": 50, "price": NumberDecimal("6") } NumberDecimal("4.50")
true
{"_id": 4, "item": "eraser", "qty": 150, "price": NumberDecimal("3") } NumberDecimal("1.50")
true
{"_id": 5, "item": "legal pad", "qty": 42, "price": NumberDecimal("10") } NumberDecimal("7.50")
false

The db.collection.find() operation returns the documents whose calculated discount price is less
than NumberDecimal("5"):

{ _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.

$text

$text performs a text query on the content of the fields indexed with a text index.

Syntax

A $text expression has the following syntax:

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

Examples

The following examples assume a collection articles that has a version 3 text index on the field
subject:

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

Populate the collection with the following documents:

db.articles.insertMany( [
{ _id: 1, subject: "coffee", author: "xyz", views: 50 },
{ _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
{ _id: 3, subject: "Baking a cake", author: "abc", views: 90 },
{ _id: 4, subject: "baking", author: "xyz", views: 100 },
{ _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
{ _id: 6, subject: "Сырники", author: "jkl", views: 80 },
{ _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
{ _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
])

$text with a Single Word

The following example specifies a $search string of coffee:

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

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

{ _id: 1, subject: 'coffee', author: 'xyz', views: 50 },


{ _id: 7, subject: 'coffee and cream', author: 'efg', views: 10 },
{ _id: 2, subject: 'Coffee Shopping', author: 'efg', views: 5 }

Match Any of the $search Terms

If the $search string is a space-delimited string, $text performs a logical OR operation on each term
and returns documents that contain any of the terms.

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

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

This operation returns documents that contain either bake or coffee or cake in the indexed subject
field, or more precisely, the stemmed version of these words:

{ "_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 }

$text with an Exact String

To match an exact multi-word string as a single term, escape the quotes.

The following example matches the exact string coffee shop:

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

This operation returns documents that contain the string coffee shop:

{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }


The following example matches the strings coffee shop and Cafe con Leche. This is a logical OR of
the two strings.

db.articles.find( { $text: { $search: "\'coffee shop\' \'Cafe con Leche\'" } } )

This operation returns documents that contain both the strings, including documents that contain
terms from both the strings:

[
{ _id: 8, subject: 'Cafe con Leche', author: 'xyz', views: 10 },
{ _id: 5, subject: 'Café Con Leche', author: 'abc', views: 200 },
{ _id: 1, subject: 'coffee', author: 'xyz', views: 50 },
{ _id: 7, subject: 'coffee and cream', author: 'efg', views: 10 },
{ _id: 2, subject: 'Coffee Shopping', author: 'efg', views: 5 }
]

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 excludes the documents that contain those terms from the results.

The following example matches documents that contain the word coffee but do not contain
the term shop, or more precisely the stemmed version of the words:

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

The operation returns the following documents:

{ "_id" : 7, "subject" : "coffee and cream", "author" : "efg", "views" : 10 }


{ "_id" : 1, "subject" : "coffee", "author" : "xyz", "views" : 50 }

Case Sensitivity

To enable case sensitivity, specify $caseSensitive: true. Specifying $caseSensitive: true may
impact performance.

Case Sensitivity with a Term


The following example performs a case sensitive query for the term Coffee:

db.articles.find( { $text: { $search: "Coffee", $caseSensitive: true } } )

The operation matches just the following document:

{ "_id" : 2, "subject" : "Coffee Shopping", "author" : "efg", "views" : 5 }

$mod

Select documents where the value of a field divided by a divisor has the specified remainder. That
is, $mod performs a modulo operation to select documents. The first argument is the dividend, and
the second argument is the remainder.
Syntax: { field: { $mod: [ divisor, remainder ] } }

db.inventory.insertMany( [
{ "_id" : 1, "item" : "abc123", "qty" : 0 },
{ "_id" : 2, "item" : "xyz123", "qty" : 5 },
{ "_id" : 3, "item" : "ijk123", "qty" : 12 }
])

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

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

The query returns the following documents:

[
{ '_id' : 1, 'item' : 'abc123', 'qty' : 0 },
{ '_id' : 3, 'item' : 'ijk123', 'qty' : 12 }
]

db.employees.insertMany( [
{ "_id" : 1, "name" : "Rob", "salary" : 37000 },
{ "_id" : 2, "name" : "Trish", "salary" : 65000 },
{ "_id" : 3, "name" : "Zeke", "salary" : 99999 },
{ "_id" : 4, "name" : "Mary", "salary" : 200000 }
])

A company is giving a $1,000 raise to all employees earning less than $100,000.

The following command matches all employees who earn less than $100,000 and have not received
a raise, increments those salaries by $1,000, and sets raiseApplied to true:

db.employees.updateMany(
{ salary: { $lt: 100000 }, raiseApplied: { $ne: true } },
{ $inc: { salary: 1000 }, $set: { raiseApplied: true } }
)

updateMany() modifies the matching employee documents individually. The individual document
updates are atomic operations, but the updateMany() operation as a whole is not atomic.

If the operation fails to update all matched documents, you can safely rerun an idempotent
command until no additional documents match the specified filter. In this case, each document's
salary field is only updated one time regardless of how many times it is retried because the
command is idempotent.

After all eligible employees have received their raises, you can remove the raiseApplied field with
the following command:
db.employees.updateMany(
{ },
{ $unset: { raiseApplied: 1 } }
)

You might also like