> For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

# $filter (expression operator)

## Definition

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.

## Compatibility

You can use `$filter` for deployments hosted in the following environments:

- [MongoDB Atlas](https://www.mongodb.com/docs/atlas): The fully managed service for MongoDB deployments in the cloud

* [MongoDB Enterprise](https://www.mongodb.com/docs/manual/administration/install-enterprise.md#std-label-install-mdb-enterprise): The subscription-based, self-managed version of MongoDB

* [MongoDB Community](https://www.mongodb.com/docs/manual/administration/install-community.md#std-label-install-mdb-community-edition): The source-available, free-to-use, and self-managed version of MongoDB

## Syntax

[`$filter`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#mongodb-expression-exp.-filter) has the following syntax:

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

| Field | Specification |
| --- | --- |
| `input` | An [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) 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](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#std-label-aggregation-variables) 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](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#std-label-aggregation-variables) 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`](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#mongodb-variable-variable.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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#std-label-filter-index-example) and [Use `$$IDX` to Access the Index.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#std-label-filter-IDX-example) **New in version 8.3** |
| `cond` | An [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) 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`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#mongodb-expression-exp.-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`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#mongodb-expression-exp.-filter) returns all matching array elements. If the limit is `null`, [`$filter`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#mongodb-expression-exp.-filter) returns all matching array elements. |

For more information on expressions, see [Expressions.](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions)

## Behavior

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

## Examples

The following examples use a `sales` collection with these documents:

```javascript
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`:

```javascript
db.sales.aggregate( [
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: { $gte: [ "$$item.price", 100 ] }
            }
         }
      }
   }
] )
```

**Output:**

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

The example uses the `limit` field to specify the number of matching elements returned in each `items` array.

```javascript
db.sales.aggregate( [
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: { $gte: [ "$$item.price", 100 ] },
               limit: 1
            }
         }
      }
   }
] )
```

**Output:**

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

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.

```javascript
db.sales.aggregate( [
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: { $gte: [ "$$item.price", 100] },
               limit: 5
            }
         }
      }
   }
] )
```

**Output:**

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

The following aggregation filters for `items` that have a `name` value of `pen`.

```javascript
db.sales.aggregate( [
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: { $eq: [ "$$item.name", "pen"] }
            }
         }
      }
   }
] )
```

**Output:**

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

The following aggregation uses [`$regexMatch`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexmatch.md#mongodb-expression-exp.-regexMatch) to filter for `items` that have a `name` value that starts with `p`:

```javascript
db.sales.aggregate( [
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: {
                  $regexMatch: { input: "$$item.name", regex: /^p/ }
               }
            }
         }
      }
   }
] )
```

**Output:**

```javascript
[
   {
      _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:

```javascript
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.

```javascript
db.people.aggregate( [
   {
      $project: {
         _id: 0,
         name: 1,
         secondaryHobbies: {
            $filter: {
               input: "$hobbies",
               arrayIndexAs: "myIndex",
               cond: { $eq: [ { $mod: [ "$$myIndex", 2 ] }, 0 ] }
            }
         }
      }
   }
] )
```

Output:

```javascript
[
   { "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`](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#mongodb-variable-variable.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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter.md#std-label-filter-index-example), but uses `$$IDX` instead of `arrayIndexAs`:

```javascript
db.people.aggregate( [
   {
      $project: {
         _id: 0,
         name: 1,
         secondaryHobbies: {
            $filter: {
               input: "$hobbies",
               cond: { $eq: [ { $mod: [ "$$IDX", 2 ] }, 0 ] }
            }
         }
      }
   }
] )
```
