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

# $regexFindAll (expression operator)

## Definition

Provides regular expression (regex) pattern matching capability in aggregation expressions. The operator returns an array of documents that contains information on each match. If a match is not found, returns an empty array.

## Syntax

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

```javascript
{ $regexFindAll: { input: <expression> , regex: <expression>, options: <expression> } }
```

| Field | Description |
| --- | --- |
| [input](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-input) | The string on which you wish to apply the [regex pattern](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexmatch.md#std-label-regexMatch-regex). Can be a string or any valid [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) that resolves to a string. |
| [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) | The regex pattern to apply. Can be any valid [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) that resolves to either a string or regex pattern `/<pattern>/`. When using the regex `/<pattern>/`, you can also specify the regex options `i` and `m` (but not the `s` or `x` options): `"pattern"`; `/<pattern>/`; `/<pattern>/<options>` Alternatively, you can also specify the regex options with the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexmatch.md#std-label-regexMatch-options) field. To specify the `s` or `x` options, you must use the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexmatch.md#std-label-regexMatch-options) field. You cannot specify options in both the `regex` and the `options` field. |
| [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) | *Optional*. The following `<options>` are available for use with regular expression. You cannot specify options in both the `regex` and the `options` field. `i`: Case insensitivity to match both upper and lower cases. You can specify the option in the `options` field or as part of the regex field.; `m`: For patterns that include anchors (that is, `^` for the start, `$` for the end), match at the beginning or end of each line for strings with multiline values. Without this option, these anchors match at beginning or end of the string.If the pattern contains no anchors or if the string value has no newline characters (e.g. `\n`), the `m` option has no effect.; `x`: "Extended" capability to ignore all white space characters in the pattern unless escaped or included in a character class.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 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 (that is, code 11).You can specify the option only in the `options` field.; `s`: Allows the dot character (that is, `.`) to match all characters *including* newline characters.You can specify the option only in the `options` field. |

### Returns

The operator returns an array:

- If the operator does not find a match, the operator returns an empty array.

- If the operator finds a match, the operator returns an array of documents that contains the following information for each match:

  - the matching string in the [input,](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-input)

  - the [code point](http://www.unicode.org/glossary/#code_point) index (not byte index) of the matching string in the [input](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-input), and

  - An array of the strings that corresponds to the groups captured by the matching string. Capturing groups are specified with unescaped parenthesis `()` in the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern.

  ```javascript
  [ { "match" : <string>, "idx" : <num>, "captures" : <array of strings> }, ... ]
  ```

**See also:**

- [`$regexFind`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfind.md#mongodb-expression-exp.-regexFind)

- [`$regexMatch`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexmatch.md#mongodb-expression-exp.-regexMatch)

## Behavior

### PCRE Library

Starting in version 6.1, MongoDB uses the PCRE2 (Perl Compatible Regular Expressions) library to implement regular expression pattern matching. To learn more about PCRE2, see the [PCRE Documentation.](https://www.pcre.org/current/doc/html/)

### $regexFindAll and Collation

String matching for `$regexFindAll` is always case-sensitive and diacritic-sensitive. `$regexFindAll` ignores the collation specified for the collection, [`db.collection.aggregate()`](https://www.mongodb.com/docs/manual/reference/method/db.collection.aggregate.md#mongodb-method-db.collection.aggregate), and the index, if used.

For example, create a collection with collation strength `1`, meaning the collation only compares base characters and ignores differences such as case and diacritics:

```javascript
db.createCollection( "restaurants", { collation: { locale: "fr", strength: 1 } } )
```

Insert the following documents:

```javascript
db.restaurants.insertMany( [
   { _id: 1, category: "café", status: "Open" },
   { _id: 2, category: "cafe", status: "open" },
   { _id: 3, category: "cafE", status: "open" }
] )
```

The following uses the collection's collation to perform a case-insensitive and diacritic-insensitive match:

```javascript
db.restaurants.aggregate( [ { $match: { category: "cafe" } } ] )
```

**Output:**

```javascript
[
   { _id: 1, category: 'café', status: 'Open' },
   { _id: 2, category: 'cafe', status: 'open' },
   { _id: 3, category: 'cafE', status: 'open' }
]
```

However, `$regexFindAll` ignores collation. The following regular expression pattern matching examples are case-sensitive and diacritic sensitive:

```javascript
db.restaurants.aggregate( [
   {
      $addFields: {
         resultObject: { $regexFindAll: { input: "$category", regex: /cafe/ } }
      }
   }
] )

db.restaurants.aggregate( [
   {
      $addFields: {
         resultObject: { $regexFindAll: { input: "$category", regex: /cafe/ } }
      }
   }
],
   { collation: { locale: "fr", strength: 1 } } // Ignored in the $regexFindAll
)
```

Both operations return the following:

```javascript
{ "_id" : 1, "category" : "café", "resultObject" : null }
{ "_id" : 2, "category" : "cafe", "resultObject" : { "match" : "cafe", "idx" : 0, "captures" : [ ] } }
{ "_id" : 3, "category" : "cafE", "resultObject" : null }
```

Because the query ignores the collation, it requires an exact match on the `category` string (including case and accent marks), meaning only document `_id: 2` is matched.

To perform a case-insensitive regex pattern matching, use the [`i` Option](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-example-i-options) instead. See [`i` Option](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-example-i-options) for an example.

### `captures` Output Behavior

If your [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern contains capture groups and the pattern finds a match in the [input](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-input), the `captures` array in the results corresponds to the groups captured by the matching string. Capture groups are specified with unescaped parentheses `()` in the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern. The length of the `captures` array equals the number of capture groups in the pattern and the order of the array matches the order in which the capture groups appear.

Create a sample collection named `contacts` with the following documents:

```javascript
db.contacts.insertMany([
  { "_id": 1, "fname": "Carol", "lname": "Smith", "phone": "718-555-0113" },
  { "_id": 2, "fname": "Daryl", "lname": "Doe", "phone": "212-555-8832" },
  { "_id": 3, "fname": "Polly", "lname": "Andrews", "phone": "208-555-1932" },
  { "_id": 4, "fname": "Colleen", "lname": "Duncan", "phone": "775-555-0187" },
  { "_id": 5, "fname": "Luna", "lname": "Clarke", "phone": "917-555-4414" }
])
```

The following pipeline applies the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern `/(C(ar)*)ol/` to the `fname` field:

```javascript
db.contacts.aggregate([
  {
    $project: {
      returnObject: {
        $regexFindAll: { input: "$fname", regex: /(C(ar)*)ol/ }
      }
    }
  }
])
```

The [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern finds a match with `fname` values `Carol` and `Colleen`:

```javascript
{ "_id" : 1, "returnObject" : [ { "match" : "Carol", "idx" : 0, "captures" : [ "Car", "ar" ] } ] }
{ "_id" : 2, "returnObject" : [ ] }
{ "_id" : 3, "returnObject" : [ ] }
{ "_id" : 4, "returnObject" : [ { "match" : "Col", "idx" : 0, "captures" : [ "C", null ] } ] }
{ "_id" : 5, "returnObject" : [ ] }
```

The pattern contains the capture group `(C(ar)*)` which contains the nested group `(ar)`. The elements in the `captures` array correspond to the two capture groups. If a matching document is not captured by a group (e.g. `Colleen` and the group `(ar)`), [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) replaces the group with a null placeholder.

As shown in the previous example, the `captures` array contains an element for each capture group (using `null` for non-captures). Consider the following example which searches for phone numbers with New York City area codes by applying a logical `or` of capture groups to the `phone` field. Each group represents a New York City area code:

```javascript
db.contacts.aggregate([
  {
    $project: {
      nycContacts: {
        $regexFindAll: { input: "$phone", regex: /^(718).*|^(212).*|^(917).*/ }
      }
    }
  }
])
```

For documents which are matched by the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) pattern, the `captures` array includes the matching capture group and replaces any non-capturing groups with `null`:

```javascript
{ "_id" : 1, "nycContacts" : [ { "match" : "718-555-0113", "idx" : 0, "captures" : [ "718", null, null ] } ] }
{ "_id" : 2, "nycContacts" : [ { "match" : "212-555-8832", "idx" : 0, "captures" : [ null, "212", null ] } ] }
{ "_id" : 3, "nycContacts" : [ ] }
{ "_id" : 4, "nycContacts" : [ ] }
{ "_id" : 5, "nycContacts" : [ { "match" : "917-555-4414", "idx" : 0, "captures" : [ null, null, "917" ] } ] }
```

## Examples

### `$regexFindAll` and Its Options

To illustrate the behavior of the [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) operator as discussed in this example, create a sample collection `products` with the following documents:

```javascript
db.products.insertMany([
   { _id: 1, description: "Single LINE description." },
   { _id: 2, description: "First lines\nsecond line" },
   { _id: 3, description: "Many spaces before     line" },
   { _id: 4, description: "Multiple\nline descriptions" },
   { _id: 5, description: "anchors, links and hyperlinks" },
   { _id: 6, description: "métier work vocation" }
])
```

By default, [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) performs a case-sensitive match. For example, the following aggregation performs a case-*sensitive* [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) on the `description` field. The regex pattern `/line/` does not specify any grouping:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /line/ } } } }
])
```

The operation returns the following:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject" : [ ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ { "match" : "line", "idx" : 6, "captures" : [ ]}, { "match" : "line", "idx" : 19, "captures" : [ ] } ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ { "match" : "line", "idx" : 23, "captures" : [ ] } ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ { "match" : "line", "idx" : 9, "captures" : [ ] }
] }

{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ ]
}
{
   "_id" : 6,
   "description" : "métier work vocation",
   "returnObject" : [ ]
}
```

The following regex pattern `/lin(e|k)/` specifies a grouping `(e|k)` in the pattern:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /lin(e|k)/ } } } }
])
```

The operation returns the following:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject": [ ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ { "match" : "line", "idx" : 6, "captures" : [ "e" ] }, { "match" : "line", "idx" : 19, "captures" : [ "e" ] } ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ { "match" : "line", "idx" : 23, "captures" : [ "e" ] } ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ { "match" : "line", "idx" : 9, "captures" : [ "e" ] } ]
}
{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ { "match" : "link", "idx" : 9, "captures" : [ "k" ] }, { "match" : "link", "idx" : 24, "captures" : [ "k" ] } ]
}
{
   "_id" : 6,
   "description" : "métier work vocation",
   "returnObject" : [ ]
}
```

In the return option, the `idx` field is the [code point](http://www.unicode.org/glossary/#code_point) index and not the byte index. To illustrate, consider the following example that uses the regex pattern `/tier/`:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /tier/ } } } }
])
```

The operation returns the following where only the last record matches the pattern and the returned `idx` is `2` (instead of 3 if using a byte index)

```javascript
{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : [ ] }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : [ ] }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : [ ] }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : [ ] }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : [ ] }
{ "_id" : 6, "description" : "métier work vocation",
             "returnObject" : [ { "match" : "tier", "idx" : 2, "captures" : [ ] } ] }
```

#### `i` Option

**Note:**

You cannot specify options in both the `regex` and the `options` field.

To perform case-*insensitive* pattern matching, include the [i](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) option as part of the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) field or in the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) field:

```javascript
// Specify i as part of the regex field
{ $regexFindAll: { input: "$description", regex: /line/i } }

// Specify i in the options field
{ $regexFindAll: { input: "$description", regex: /line/, options: "i" } }
{ $regexFindAll: { input: "$description", regex: "line", options: "i" } }
```

For example, the following aggregation performs a case-*insensitive* [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) on the `description` field. The regex pattern `/line/` does not specify any grouping:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /line/i } } } }
])
```

The operation returns the following documents:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject" : [ { "match" : "LINE", "idx" : 7, "captures" : [ ] } ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ { "match" : "line", "idx" : 6, "captures" : [ ] }, { "match" : "line", "idx" : 19, "captures" : [ ] } ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ { "match" : "line", "idx" : 23, "captures" : [ ] } ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ { "match" : "line", "idx" : 9, "captures" : [ ] } ]
}
{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ ]
}
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : [ ] }
```

#### `m` Option

**Note:**

You cannot specify options in both the `regex` and the `options` field.

To match the specified anchors (e.g. `^`, `$`) for each line of a multiline string, include the [m](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) option as part of the [regex](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-regex) field or in the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) field:

```javascript
// Specify m as part of the regex field
{ $regexFindAll: { input: "$description", regex: /line/m } }

// Specify m in the options field
{ $regexFindAll: { input: "$description", regex: /line/, options: "m" } }
{ $regexFindAll: { input: "$description", regex: "line", options: "m" } }
```

The following example includes both the `i` and the `m` options to match lines starting with either the letter `s` or `S` for multiline strings:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /^s/im } } } }
])
```

The operation returns the following:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject" : [ { "match" : "S", "idx" : 0, "captures" : [ ] } ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ { "match" : "s", "idx" : 12, "captures" : [ ] } ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ ]
}
{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ ]
}
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : [ ] }
```

#### `x` Option

**Note:**

You cannot specify options in both the `regex` and the `options` field.

To ignore all unescaped white space characters and comments (denoted by the un-escaped hash `#` character and the next new-line character) in the pattern, include the [s](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) option in the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) field:

```javascript
// Specify x in the options field
{ $regexFindAll: { input: "$description", regex: /line/, options: "x" } }
{ $regexFindAll: { input: "$description", regex: "line", options: "x" } }
```

The following example includes the `x` option to skip unescaped white spaces and comments:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex: /lin(e|k) # matches line or link/, options:"x" } } } }
])
```

The operation returns the following:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject" : [ ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ { "match" : "line", "idx" : 6, "captures" : [ "e" ] }, { "match" : "line", "idx" : 19, "captures" : [ "e" ] } ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ { "match" : "line", "idx" : 23, "captures" : [ "e" ] } ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ { "match" : "line", "idx" : 9, "captures" : [ "e" ] } ]
}
{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ { "match" : "link", "idx" : 9, "captures" : [ "k" ] }, { "match" : "link", "idx" : 24, "captures" : [ "k" ] } ]
}
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : [ ] }
```

#### `s` Option

**Note:**

You cannot specify options in both the `regex` and the `options` field.

To allow the dot character (i.e. `.`) in the pattern to match all characters including the new line character, include the [s](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) option in the [options](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-options) field:

```javascript
// Specify s in the options field
{ $regexFindAll: { input: "$description", regex: /m.*line/, options: "s" } }
{ $regexFindAll: { input: "$description", regex: "m.*line", options: "s" } }
```

The following example includes 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:

```javascript
db.products.aggregate([
   { $addFields: { returnObject: { $regexFindAll: { input: "$description", regex:/m.*line/, options: "si"  } } } }
])
```

The operation returns the following:

```javascript
{
   "_id" : 1,
   "description" : "Single LINE description.",
   "returnObject" : [ ]
}
{
   "_id" : 2,
   "description" : "First lines\nsecond line",
   "returnObject" : [ ]
}
{
   "_id" : 3,
   "description" : "Many spaces before     line",
   "returnObject" : [ { "match" : "Many spaces before line", "idx" : 0, "captures" : [ ] } ]
}
{
   "_id" : 4,
   "description" : "Multiple\nline descriptions",
   "returnObject" : [ { "match" : "Multiple\nline", "idx" : 0, "captures" : [ ] } ]
}
{
   "_id" : 5,
   "description" : "anchors, links and hyperlinks",
   "returnObject" : [ ]
}
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : [ ] }
```

### Use `$regexFindAll` to Parse Email from String

Create a sample collection `feedback` with the following documents:

```javascript
db.feedback.insertMany([
   { "_id" : 1, comment: "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com"  },
   { "_id" : 2, comment: "I wanted to concatenate a string" },
   { "_id" : 3, comment: "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com" },
   { "_id" : 4, comment: "It's just me. I'm testing.  fred@MongoDB.com" }
])
```

The following aggregation uses the [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) to extract all emails from the `comment` field (case insensitive).

```javascript
db.feedback.aggregate( [
    { $addFields: {
       "email": { $regexFindAll: { input: "$comment", regex: /[a-z0-9_.+-]+@[a-z0-9_.+-]+\.[a-z0-9_.+-]+/i } }
    } },
    { $set: { email: "$email.match"} }
] )
```

First Stage

The stage uses the [`$addFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addfields.md#mongodb-pipeline-pipe.-addFields) stage to add a new field `email` to the document. The new field is an array that contains the result of performing the [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) on the `comment` field:

```javascript
{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "email" : [ { "match" : "aunt.arc.tica@example.com", "idx" : 38, "captures" : [ ] } ] }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "email" : [ ] }
{ "_id" : 3, "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com", "email" : [ { "match" : "cam@mongodb.com", "idx" : 56, "captures" : [ ] }, { "match" : "c.dia@mongodb.com", "idx" : 75, "captures" : [ ] } ] }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "email" : [ { "match" : "fred@MongoDB.com", "idx" : 28, "captures" : [ ] } ] }
```

Second Stage

The stage use the [`$set`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set.md#mongodb-pipeline-pipe.-set) stage to reset the `email` array elements to the `"email.match"` value(s). If the current value of `email` is null, the new value of `email` is set to null.

```javascript
{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "email" : [ "aunt.arc.tica@example.com" ] }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "email" : [ ] }
{ "_id" : 3, "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com", "email" : [ "cam@mongodb.com", "c.dia@mongodb.com" ] }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "email" : [ "fred@MongoDB.com" ] }
```

### Use Captured Groupings to Parse User Name

Create a sample collection `feedback` with the following documents:

```javascript
db.feedback.insertMany([
   { "_id" : 1, comment: "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com"  },
   { "_id" : 2, comment: "I wanted to concatenate a string" },
   { "_id" : 3, comment: "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com" },
   { "_id" : 4, comment: "It's just me. I'm testing.  fred@MongoDB.com" }
])
```

To reply to the feedback, assume you want to parse the local-part of the email address to use as the name in the greetings. Using the `captured` field returned in the [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) results, you can parse out the local part of each email address:

```javascript
db.feedback.aggregate( [
    { $addFields: {
       "names": { $regexFindAll: { input: "$comment", regex: /([a-z0-9_.+-]+)@[a-z0-9_.+-]+\.[a-z0-9_.+-]+/i } },
    } },
    { $set: { names: { $reduce: { input:  "$names.captures", initialValue: [ ], in: { $concatArrays: [ "$$value", "$$this" ] } } } } }
] )
```

First Stage

The stage uses the [`$addFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addfields.md#mongodb-pipeline-pipe.-addFields) stage to add a new field `names` to the document. The new field contains the result of performing the [`$regexFindAll`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#mongodb-expression-exp.-regexFindAll) on the `comment` field:

```javascript
{
   "_id" : 1,
   "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com",
   "names" : [ { "match" : "aunt.arc.tica@example.com", "idx" : 38, "captures" : [ "aunt.arc.tica" ] } ]
}

{ "_id" : 2, "comment" : "I wanted to concatenate a string", "names" : [ ] }
{
   "_id" : 3,
   "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com",
   "names" : [
      { "match" : "cam@mongodb.com", "idx" : 56, "captures" : [ "cam" ] },
      { "match" : "c.dia@mongodb.com", "idx" : 75, "captures" : [ "c.dia" ] }
    ]
}
{
   "_id" : 4,
   "comment" : "It's just me. I'm testing.  fred@MongoDB.com",
   "names" : [ { "match" : "fred@MongoDB.com", "idx" : 28, "captures" : [ "fred" ] } ]
}
```

Second Stage

The stage use the [`$set`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set.md#mongodb-pipeline-pipe.-set) stage with the [`$reduce`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/reduce.md#mongodb-expression-exp.-reduce) operator to reset  `names` to an array that contains the `"$names.captures"` elements.

```javascript
{
   "_id" : 1,
   "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com",
   "names" : [ "aunt.arc.tica" ]
}
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "names" : [ ] }
{
   "_id" : 3,
   "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com",
   "names" : [ "cam", "c.dia" ]
}
{
   "_id" : 4,
   "comment" : "It's just me. I'm testing.  fred@MongoDB.com",
   "names" : [ "fred" ]
}
```

**See also:**

For more information on the behavior of the `captures` array and additional examples, see [`captures` Output Behavior.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/regexfindall.md#std-label-regexFindAll-captures-behavior)
