Docs Menu

Docs HomeDevelop ApplicationsMongoDB Manual

$regex

On this page

  • Definition
  • Compatibility
  • Syntax
  • Behavior
  • Examples

Note

This page describes regular expression search capabilities for self-managed (non-Atlas) deployments. For data hosted on MongoDB Atlas, MongoDB offers an improved full-text search solution, Atlas Search, which has its own $regex operator. To learn more, see $regex in the Atlas Search documentation.

$regex

Provides regular expression capabilities for pattern matching strings in queries.

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

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud

To use $regex, use one of the following syntaxes:

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ "<field>": { "$regex": "pattern", "$options": "<options>" } }
{ <field>: { $regex: /pattern/<options> } }

Note

To use $regex with mongodump, you must enclose the query document in single quotes ('{ ... }') to ensure that it does not interact with your shell environment.

The query document must be in Extended JSON v2 format (either relaxed or canonical/strict mode), which includes enclosing the field names and operators in quotes. For example:

mongodump -d=sample_mflix -c=movies -q='{"year": {"$regex": "20"}}'

In MongoDB, you can also use regular expression objects (i.e. /pattern/) to specify regular expressions:

{ <field>: /pattern/<options> }

For restrictions on particular syntax use, see $regex vs. /pattern/ Syntax.

$options

The following <options> are available for use with regular expression.

Option
Description
Syntax Restrictions
i
Case insensitivity to match upper and lower cases. For an example, see Perform Case-Insensitive Regular Expression Match.
m

For patterns that include anchors (i.e. ^ 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. For an example, see Multiline Match for Lines Starting with Specified Pattern.

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 $regex 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 (i.e. code 11).

Requires $regex with $options syntax
s
Allows the dot character (i.e. .) to match all characters including newline characters. For an example, see Use the . Dot Character to Match New Line.
Requires $regex with $options syntax

Note

The $regex operator does not support the global search modifier g.

To include a regular expression in an $in query expression, you can only use JavaScript regular expression objects (i.e. /pattern/ ). For example:

{ name: { $in: [ /^acme/i, /^ack/ ] } }

You cannot use $regex operator expressions inside an $in operator.

To include a regular expression in a comma-separated list of query conditions for the field, use the $regex operator. For example:

{ name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcorp' ] } }
{ name: { $regex: /acme.*corp/, $options: 'i', $nin: [ 'acmeblahcorp' ] } }
{ name: { $regex: 'acme.*corp', $options: 'i', $nin: [ 'acmeblahcorp' ] } }

To use either the x option or s options, you must use the $regex operator expression with the $options operator. For example, to specify the i and the s options, you must use $options for both:

{ name: { $regex: /acme.*corp/, $options: "si" } }
{ name: { $regex: 'acme.*corp', $options: "si" } }

To use PCRE-supported features in a regular expression that aren't supported in JavaScript, you must use the $regex operator and specify the regular expression as a string.

To match case-insensitive strings:

  • "(?i)" begins a case-insensitive match.

  • "(?-i)" ends a case-insensitive match.

For example, the regular expression "(?i)a(?-i)cme" matches strings that:

  • Begin with "a" or "A". This is a case-insensitive match.

  • End with "cme". This is a case-sensitive match.

These strings match the example regular expression:

  • "acme"

  • "Acme"

The following example uses the $regex operator to find name field strings that match the regular expression "(?i)a(?-i)cme":

{ name: { $regex: "(?i)a(?-i)cme" } }

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.

The $not operator can perform logical NOT operation on both:

  • Regular expression objects (i.e. /pattern/)

    For example:

    db.inventory.find( { item: { $not: /^p.*/ } } )
  • $regex operator expressions

    For example:

    db.inventory.find( { item: { $not: { $regex: "^p.*" } } } )
    db.inventory.find( { item: { $not: { $regex: /^p.*/ } } } )

Index use and performance for $regex queries varies depending on whether the query is case-sensitive or case-insensitive.

For case sensitive regular expression queries, if an index exists for the field, then MongoDB matches the regular expression against the values in the index, which can be faster than a collection scan.

Further optimization can occur if the regular expression is a "prefix expression", which means that all potential matches start with the same string. This allows MongoDB to construct a "range" from that prefix and only match against those values from the index that fall within that range.

A regular expression is a "prefix expression" if it starts with a caret (^) or a left anchor (\A), followed by a string of simple symbols. For example, the regex /^abc.*/ will be optimized by matching only against the values from the index that start with abc.

Additionally, while /^a/, /^a.*/, and /^a.*$/ match equivalent strings, they have different performance characteristics. All of these expressions use an index if an appropriate index exists; however, /^a.*/, and /^a.*$/ are slower. /^a/ can stop scanning after matching the prefix.

Case-insensitive indexes typically do not improve performance for $regex queries. The $regex implementation is not collation-aware and cannot utilize case-insensitive indexes efficiently.

The examples in this section use the following products collection:

db.products.insertMany( [
{ _id: 100, sku: "abc123", description: "Single line description." },
{ _id: 101, sku: "abc789", description: "First line\nSecond line" },
{ _id: 102, sku: "xyz456", description: "Many spaces before line" },
{ _id: 103, sku: "xyz789", description: "Multiple\nline description" },
{ _id: 104, sku: "Abc789", description: "SKU starts with A" }
] )

The following example matches all documents where the sku field is like "%789":

db.products.find( { sku: { $regex: /789$/ } } )

The example is analogous to the following SQL LIKE statement:

SELECT * FROM products
WHERE sku like "%789";

Example output:

[
{ _id: 101, sku: 'abc789', description: 'First line\nSecond line' },
{ _id: 103, sku: 'xyz789', description: 'Multiple\nline description' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

The following example uses the i option perform a case-insensitive match for documents with sku value that starts with ABC.

db.products.find( { sku: { $regex: /^ABC/i } } )

Example output:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' },
{ _id: 101, sku: 'abc789', description: 'First line\nSecond line' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

The following example uses the m option to match lines starting with the letter S for multiline strings:

db.products.find( { description: { $regex: /^S/, $options: 'm' } } )

Example output:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' },
{ _id: 101, sku: 'abc789', description: 'First line\nSecond line' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

Without the m option, the example output is:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

If the $regex pattern does not contain an anchor, the pattern matches against the string as a whole, as in the following example:

db.products.find( { description: { $regex: /S/ } } )

Example output:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' },
{ _id: 101, sku: 'abc789', description: 'First line\nSecond line' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

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

db.products.find( { description: { $regex: /m.*line/, $options: 'si' } } )

Example output:

[
{ _id: 102, sku: 'xyz456', description: 'Many spaces before line' },
{ _id: 103, sku: 'xyz789', description: 'Multiple\nline description' }
]

Without the s option, the example output is:

[
{ _id: 102, sku: 'xyz456', description: 'Many spaces before line' }
]

The following example uses the x option ignore white spaces and the comments, denoted by the # and ending with the \n in the matching pattern:

var pattern = "abc #category code\n123 #item number"
db.products.find( { sku: { $regex: pattern, $options: "x" } } )

Example output:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' }
]

The following example uses the regular expression "(?i)a(?-i)bc" to match sku field strings that contain:

  • "abc"

  • "Abc"

db.products.find( { sku: { $regex: "(?i)a(?-i)bc" } } )

Example output:

[
{ _id: 100, sku: 'abc123', description: 'Single line description.' },
{ _id: 101, sku: 'abc789', description: 'First line\nSecond line' },
{ _id: 104, sku: 'Abc789', description: 'SKU starts with A' }
]

New in version 6.1.

By default, certain regex options (such as /b and /w) only recognize ASCII characters. This can cause unexpected results when performing regex matches against UTF-8 characters.

Starting in MongoDB 6.1, you can specify the *UCP regex option to match UTF-8 characters.

Important

Performance of UCP Option

The *UCP option results in slower queries than those without the option specified because *UCP requires a multistage table lookup to perform the match.

For example, consider the following documents in a songs collection:

db.songs.insertMany( [
{ _id: 0, "artist" : "Blue Öyster Cult", "title": "The Reaper" },
{ _id: 1, "artist": "Blue Öyster Cult", "title": "Godzilla" },
{ _id: 2, "artist" : "Blue Oyster Cult", "title": "Take Me Away" }
] )

The following regex query uses the \b option in a regex match. The \b option matches a word boundary.

db.songs.find( { artist: { $regex: /\byster/ } } )

Example output:

[
{ _id: 0, artist: 'Blue Öyster Cult', title: 'The Reaper' },
{ _id: 1, artist: 'Blue Öyster Cult', title: 'Godzilla' }
]

The previous results are unexpected because none of the words in the returned artist fields begin with the matched string (yster). The Ö character in documents _id: 0 and _id: 1 is ignored when performing the match because it is a UTF-8 character.

The expected result is that the query does not return any documents.

To allow the query to recognize UTF-8 characters, specify the *UCP option before the pattern:

db.songs.find( { artist: { $regex: "(*UCP)/\byster/" } } )

The previous query does not return any documents, which is the expected result.

Tip

Escape Characters for Regex Patterns

When specifying *UCP or any other regular expression option, ensure that you use the correct escape characters for your shell or driver.

←  $mod$text →