MongoDB $regexFindAll Operator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $regexFindAll?

$regexFindAll is a MongoDB aggregation expression that finds every regular-expression match in a string and returns an array of match objects. No matches → []. Each object has match, idx, and captures.

Remember
$regexFindAll ≈ String.matchAll → array of hits

{ $regexFindAll: {
    input: <string>,
    regex: <pattern>,
    options: <options>   // optional
} }

each hit → { match, idx, captures }
no hits  → []
idx      → code point index (not bytes)
UsePrefer
Every match + details$regexFindAll
First match only$regexFind
True / false only$regexMatch

How to Use $regexFindAll in MongoDB

Pass the input string, the pattern, and optional regex options.

  1. Choose an expression stage ($addFields or $project).
  2. Set input to a string field (for example "$text").
  3. Set regex to a pattern string or /pattern/.
  4. Optional: add options such as "i" (do not also put options on the regex literal).
PieceRequired?Role
inputYesString to search
regexYesPattern as string or /.../
optionsNoi, m, x, s (not both here and on the regex)

Pseudocode

Pseudocode
for each document:
    s = evaluate(input)
    pattern = evaluate(regex)
    hits = []
    for each match of pattern in s (left to right):
        hits.push({
            match: matchedText,
            idx: codePointIndex,
            captures: [ group1, group2, ... ]  // null if unused
        })
    emit { ..., field: hits }   // [] when none

Cheat Sheet

Keep these facts handy while writing regex find-all expressions.

TopicDetail
TypeAggregation expression (not a find filter alone)
Syntax{ $regexFindAll: { input, regex, options? } }
ResultArray of { match, idx, captures }
No match[] (empty array)
idxCode point index of the match start
Case-insensitiveoptions: "i" (collation is ignored)
vs $regexFindAll matches vs first match only

Live Preview

Text: "Call 555-0199 or 555-0100 today". Watch $regexFindAll collect every phone-like match.

Simulates $regexFindAll match objects (same idea as the mongosh examples).

Result
input = "Call 555-0199 or 555-0100 today"
regex = /\d{3}-\d{4}/
$regexFindAll → 2 hits

[
  { match: "555-0199", idx: 5, captures: [] },
  { match: "555-0100", idx: 17, captures: [] }
]

Worked Walkthrough — Two Phone Numbers

Text "Call 555-0199 or 555-0100 today" with pattern \d{3}-\d{4}.

Calculation
input  = "Call 555-0199 or 555-0100 today"
indexes: 0123456789...

scan left → right:
  first hit  "555-0199" at idx 5
  next hit   "555-0100" at idx 17

$result = [
  { match: "555-0199", idx: 5,  captures: [] },
  { match: "555-0100", idx: 17, captures: [] }
]

If the pattern never hits → []

MongoDB Examples

We use a small notes collection with a text field. First we collect every phone-like match, then we pull capture groups from product codes. Insert the sample data once in mongosh.

Example 1 — Sample Data

Imagine three short notes. Each has an id and a text string. We save them in a collection named notes.

mongosh
db.notes.insertMany([
  { _id: 1, text: "Call 555-0199 or 555-0100 today" },
  { _id: 2, text: "No phones here" },
  { _id: 3, text: "Codes: A12 and B34" }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps three documents in notes. Run find() to see them:

mongosh
db.notes.find()

Read those documents like this:

Field in MongoDBExamplePlain English
_id1Note id for this lesson
text"Call 555-0199 or 555-0100 today"String we will search with regex
Picture
Note 1 text:

  "Call 555-0199 or 555-0100 today"
        ^------^    ^------^
        idx 5       idx 17

Pattern \d{3}-\d{4} finds both numbers.

How It Works

  1. Insert once. insertMany adds three note documents.
  2. MongoDB stores strings as written. Spaces and hyphens count toward idx.
  3. find() shows the same shape. What you inserted is what you get back—ready for $regexFindAll next.

Example 2 — Find All Phone-Like Matches

Goal: for each note, collect every ###-#### style number into phones.

mongosh
db.notes.aggregate([
  {
    $addFields: {
      phones: {
        $regexFindAll: {
          input: "$text",
          regex: /\d{3}-\d{4}/
        }
      }
    }
  }
]);

How It Works

  1. Read the stored string. input: "$text" is the note body.
  2. Apply the pattern. \d{3}-\d{4} means three digits, a hyphen, four digits.
  3. Collect every hit. Note 1 gets two objects; each has match and start idx.
  4. No hits → []. Notes 2 and 3 return an empty array, not null.

Example 3 — Capture Groups

Same notes, but pull letter + digits from codes like A12 using groups ([A-Z])(\d+).

mongosh
db.notes.aggregate([
  {
    $addFields: {
      codes: {
        $regexFindAll: {
          input: "$text",
          regex: /([A-Z])(\d+)/
        }
      }
    }
  }
]);

How It Works

  1. Same stored documents. Still using the three notes from Example 1.
  2. Groups in the pattern. ([A-Z]) is group 1; (\d+) is group 2.
  3. fills captures. For A12 → ["A", "12"]; same idea for B34.
  4. Other notes stay empty. No letter+digits codes → [].

Edge Cases & Pitfalls

Check these before using $regexFindAll in production pipelines.

empty

No match → [] not null

$regexFind returns null when nothing matches. $regexFindAll returns an empty array. Test with $size or emptiness checks accordingly.

options

Do not double-specify options

Put flags either on the regex literal (/pat/i) or in options—not both. Use options for s / x.

idx

idx is code points

Slice with $substrCP, not $substrBytes, when using idx.

cost

Regex can be expensive

Scanning long strings with complex patterns is slower than simple field filters. Prefer $match early when possible.

Performance Notes

ApproachCostBest for
$regexFindAllO(string × pattern work)Extracting every match
$regexFindStops after first hitOnly need one match
$regexMatchCheapest of the threeBoolean existence checks

Prefer simpler operators when you do not need every match object. Keep patterns focused, and filter documents early so regex runs on fewer rows.

Key Takeaways

  • Role: every regex match → array of objects.
  • Shape: { match, idx, captures } per hit.
  • No hits: returns [], not null.
  • First only / boolean? use $regexFind / $regexMatch.

One line: $regexFindAll answers “where are all the matches?”—as an array of match / idx / captures objects.

Frequently Asked Questions

$regexFindAll searches a string for every regular expression match and returns an array of objects. Each object has match (matched text), idx (code point start index), and captures (capture groups). If nothing matches, it returns an empty array [].
Use { $regexFindAll: { input: <string>, regex: <pattern>, options: <options> } } inside stages like $project and $addFields. The options field is optional.
$regexFind returns only the first match as one object (or null). $regexFindAll returns every match as an array of match objects (or [] when none).
Use $regexFindAll when you need matched text, positions, or capture groups for every occurrence. Use $regexMatch when you only need true or false.
idx is a Unicode code point index (character position), not a UTF-8 byte index. Pair it with $substrCP if you slice by that index.
No. $regexFindAll ignores collation and is case-sensitive by default. Use the i option for case-insensitive matching.

Next: $regexMatch

Test whether a string matches a regex (boolean).

$regexMatch tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful