Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Docs Menu
Docs Home
/ /

$filter (expression operator)

$filter

Selects a subset of an array to return based on the specified condition. Returns an array with only those elements that match the condition. The returned elements are in the original order.

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

$filter has the following syntax:

{
$filter:
{
input: <array>,
as: <string>,
arrayIndexAs: <string>,
cond: <expression>,
limit: <number expression>
}
}
Field
Specification

input

An expression that resolves to an array.

If input resolves to null or refers to a missing field, $filter returns null.

If input resolves to a non-array, non-null value, the pipeline errors.

as

Optional. A name for the variable that represents each individual element of the input array. If no name is specified, the variable name defaults to this.

arrayIndexAs

Optional. A name for the aggregation variable that represents the index of the current element in the input array. The first array element index is 0.

You can use the variable name in an expression. For example, if you specify arrayIndexAs: "myIndex", you use $$myIndex in the expression. $$myIndex returns the index of the current element in the input array.

If you omit arrayIndexAs, you can use the $$IDX system variable in the expression to return the index of the current element.

For examples, see Access the Index of Each Item in an Array and Use $$IDX to Access the Index.

New in version 8.3.

cond

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 input array individually with the variable name specified in as.

limit

Optional. A number expression that restricts the number of matching array elements that $filter returns. You cannot specify a limit less than 1. The matching array elements are returned in the order they appear in the input array.

If the specified limit is greater than the number of matching array elements, $filter returns all matching array elements. If the limit is null, $filter returns all matching array elements.

For more information on expressions, see Expressions.

Example
Results
{
$filter: {
input: [ 1, "a", 2, null, 3.1, Long(4), "5" ],
as: "num",
cond: { $isNumber: "$$num" }
}
}

[ 1, 2, 3.1, Long(4) ]

{
$filter: {
input: [ 1, "a", 2, null, 3.1, Long(4), "5" ],
as: "num",
cond: { $isNumber: "$$num" },
limit: 2
}
}

[ 1, 2 ]

{
$filter: {
input: [ 1, "a", 2, null, 3.1, Long(4), "5" ],
as: "num",
cond: { $isNumber: "$$num" },
limit: { $add: [ 0, 1 ] }
}
}

[ 1 ]

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" }
]
}
] )

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: [] }
]

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: [] }
]

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: [] }
]

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: [] }
]

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' } ]
}
]

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.

  • secondaryHobbies array 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 }
]

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 ] }
}
}
}
}
] )

Back

$expMovingAvg

On this page