Definition
Compatibility
You can use $filter for deployments hosted in the following
environments:
MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
MongoDB Enterprise: The subscription-based, self-managed version of MongoDB
MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB
Syntax
$filter has the following syntax:
{ $filter: { input: <array>, as: <string>, arrayIndexAs: <string>, cond: <expression>, limit: <number expression> } }
Field | Specification |
|---|---|
| An expression that resolves to an array. If If |
| Optional. A name for the variable that represents each
individual element of the |
| Optional. A name for the aggregation variable that represents the index of the current
element in the You can use the variable name in an expression. For example, if you
specify If you omit For examples, see Access the Index of Each Item in an Array and
Use New in version 8.3. |
| An expression that resolves
to a boolean value used to determine if an element should be
included in the output array. The expression references each
element of the |
| Optional. A number expression that restricts the number of matching
array elements that If the specified |
For more information on expressions, see Expressions.
Behavior
Example | Results | ||||||||
|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||
|
| ||||||||
|
|
Examples
A collection sales has the following documents:
db.sales.insertMany( [ { _id: 0, items: [ { item_id: 43, quantity: 2, price: 10, name: "pen" }, { item_id: 2, quantity: 1, price: 240, name: "briefcase" } ] }, { _id: 1, items: [ { item_id: 23, quantity: 3, price: 110, name: "notebook" }, { item_id: 103, quantity: 4, price: 5, name: "pen" }, { item_id: 38, quantity: 1, price: 300, name: "printer" } ] }, { _id: 2, items: [ { item_id: 4, quantity: 1, price: 23, name: "paper" } ] } ] )
Filter Based on Number Comparison
The following example filters the items array to only include
documents that have a price greater than or equal to 100:
db.sales.aggregate( [ { $project: { items: { $filter: { input: "$items", as: "item", cond: { $gte: [ "$$item.price", 100 ] } } } } } ] )
[ { _id: 0, items: [ { item_id: 2, quantity: 1, price: 240, name: 'briefcase' } ] }, { _id: 1, items: [ { item_id: 23, quantity: 3, price: 110, name: 'notebook' }, { item_id: 38, quantity: 1, price: 300, name: 'printer' } ] }, { _id: 2, items: [] } ]
Use the limit Field
This example uses the sales collection from the previous example.
The example uses the limit field to specify the number of matching
elements returned in each items array.
db.sales.aggregate( [ { $project: { items: { $filter: { input: "$items", as: "item", cond: { $gte: [ "$$item.price", 100 ] }, limit: 1 } } } } ] )
[ { _id: 0, items: [ { item_id: 2, quantity: 1, price: 240, name: 'briefcase' } ] }, { _id: 1, items: [ { item_id: 23, quantity: 3, price: 110, name: 'notebook' } ] }, { _id: 2, items: [] } ]
limit Greater than Possible Matches
This example uses the sales collection from the previous example.
The example uses a limit field value that is larger than the
possible number of matching elements that can be returned. In this case,
limit does not affect the query results and returns all documents
matching the $gte filter criteria.
db.sales.aggregate( [ { $project: { items: { $filter: { input: "$items", as: "item", cond: { $gte: [ "$$item.price", 100] }, limit: 5 } } } } ] )
[ { _id: 0, items: [ { item_id: 2, quantity: 1, price: 240, name: 'briefcase' } ] }, { _id: 1, items: [ { item_id: 23, quantity: 3, price: 110, name: 'notebook' }, { item_id: 38, quantity: 1, price: 300, name: 'printer' } ] }, { _id: 2, items: [] } ]
Filter Based on String Equality Match
This example uses the sales collection from the previous example.
The following aggregation filters for items that have a name
value of pen.
db.sales.aggregate( [ { $project: { items: { $filter: { input: "$items", as: "item", cond: { $eq: [ "$$item.name", "pen"] } } } } } ] )
[ { _id: 0, items: [ { item_id: 43, quantity: 2, price: 10, name: 'pen' } ] }, { _id: 1, items: [ { item_id: 103, quantity: 4, price: 5, name: 'pen' } ] }, { _id: 2, items: [] } ]
Filter Based on Regular Expression Match
This example uses the sales collection from the previous example.
The following aggregation uses $regexMatch to filter for
items that have a name value that starts with p:
db.sales.aggregate( [ { $project: { items: { $filter: { input: "$items", as: "item", cond: { $regexMatch: { input: "$$item.name", regex: /^p/ } } } } } } ] )
[ { _id: 0, items: [ { item_id: 43, quantity: 2, price: 10, name: 'pen' } ] }, { _id: 1, items: [ { item_id: 103, quantity: 4, price: 5, name: 'pen' }, { item_id: 38, quantity: 1, price: 300, name: 'printer' } ] }, { _id: 2, items: [ { item_id: 4, quantity: 1, price: 23, name: 'paper' } ] } ]
Access the Index of Each Item in an Array
Create a sample collection named people with these documents:
db.people.insertMany( [ { _id: 1, name: "Melissa", hobbies: [ "softball", "drawing", "reading" ] }, { _id: 2, name: "Brad", hobbies: [ "gaming", "skateboarding" ] }, { _id: 3, name: "Scott", hobbies: [ "basketball", "music", "fishing" ] }, { _id: 4, name: "Tracey", hobbies: [ "acting", "yoga" ] }, { _id: 5, name: "Josh", hobbies: [ "programming" ] }, { _id: 6, name: "Claire" } ] )
The hobbies field contains an array of each person's hobbies in
ranked order. The first hobby in the array is the person's primary hobby
that the person spends the most time on. The first hobby has an array
index of 0.
The following example uses arrayIndexAs. The myIndex variable
has the index of each hobby in the hobbies array. The example
returns documents with these fields:
Person name.
secondaryHobbiesarray that includes every other hobby.
db.people.aggregate( [ { $project: { _id: 0, name: 1, secondaryHobbies: { $filter: { input: "$hobbies", arrayIndexAs: "myIndex", cond: { $eq: [ { $mod: [ "$$myIndex", 2 ] }, 0 ] } } } } } ] )
Output:
[ { "name" : "Melissa", "secondaryHobbies" : [ "softball", "reading" ] } { "name" : "Brad", "secondaryHobbies" : [ "gaming" ] } { "name" : "Scott", "secondaryHobbies" : [ "basketball", "fishing" ] } { "name" : "Tracey", "secondaryHobbies" : [ "acting" ] } { "name" : "Josh", "secondaryHobbies" : [ "programming" ] } { "name" : "Claire", "secondaryHobbies" : null } ]
Use $$IDX to Access the Index
The $$IDX variable returns the index of the current
element in the input array. You can use $$IDX if you omit the
arrayIndexAs field from the expression.
The following example returns the same documents as the example in the
previous section Access the Index of Each Item in an Array, but uses $$IDX instead
of arrayIndexAs:
db.people.aggregate( [ { $project: { _id: 0, name: 1, secondaryHobbies: { $filter: { input: "$hobbies", cond: { $eq: [ { $mod: [ "$$IDX", 2 ] }, 0 ] } } } } } ] )