HOWTO · MongoDB
How to Do Starts With Query in MongoDB
In this MongoDB article the user will learn how to do a starts with query using $regex. It provides regular expression capabilities for pattern matching strings in queries.
On this page
A common MongoDB task is finding every document in which a string field begins with a chosen prefix — for example, every user whose name starts with Ja. MongoDB has no dedicated startsWith operator, so the standard solution is a regular expression anchored at the start of the string, written with the $regex operator or as a regular-expression literal in the query filter.
The query snippets on this page use mongosh syntax, which runs in the MongoDB Shell or an equivalent driver session rather than a system shell; run them against your own deployment to see live results. The runnable script further down reproduces the same matching logic in plain JavaScript.
Use an Anchored $regex for Prefix Matches
A “starts with” match is a pattern match in which the ^ anchor pins the pattern to the first character of the string. The pattern /^Ja/ matches only values whose first two characters are Ja; a value that merely contains Ja later, such as McJane, is not a match. Without ^, the pattern /Ja/ scans the whole string and matches Ja anywhere, which turns a prefix query into a “contains” query.
The $regex operator form of a starts-with query is db.collection.find({ name: { $regex: "^Ja" } }), where:
db.collectionis the collection to search.nameis the string field to test.$regextells MongoDB to evaluate the value as a regular expression."^Ja"is the pattern:^anchors it at the start of the string, andJais the literal prefix.
In mongosh and in drivers that support regular-expression literals, you can write the same filter more compactly as db.users.find({ name: /^Ja/ }).
Because the pattern is a regular expression rather than a plain string, a prefix that contains regex metacharacters such as ., *, +, (, ), [, ], or $ must be escaped with a backslash. For example, the literal prefix v1. needs the pattern "^v1\\."; left unescaped, the . matches any character and the query no longer behaves like a literal prefix match.
Run a Starts-With Query
Suppose a users collection holds documents whose name values are John Doe, Jane Smith, Jack Johnson, Jill Jackson, and James Brown — inserted, for example, with db.users.insertMany([{ name: "John Doe" }, { name: "Jane Smith" }, { name: "Jack Johnson" }, { name: "Jill Jackson" }, { name: "James Brown" }]).
The query db.users.find({ name: { $regex: "^Ja" } }) returns the documents whose name begins with Ja: Jane Smith, Jack Johnson, and James Brown. John Doe starts with Jo and Jill Jackson starts with Ji, so the anchor excludes both.
mongosh accepts JavaScript-style regular-expression literals such as /^Ja/, but the server evaluates $regex with a PCRE-compatible engine, not JavaScript. For this anchored pattern the semantics coincide, so the following script reproduces the same matching logic in plain JavaScript and you can confirm which documents it selects:
const names = ["John Doe", "Jane Smith", "Jack Johnson", "Jill Jackson", "James Brown"];
const prefix = /^Ja/;
console.log(names.filter((name) => prefix.test(name)).join("\n"));
Jane Smith
Jack Johnson
James Brown
Choose Case-Sensitive or Case-Insensitive Matching
Regex matching in MongoDB is case-sensitive by default, so ^Ja does not match a value such as james brown. To match a prefix regardless of letter case, add the i option, written as db.users.find({ name: /^ja/i }). The equivalent $regex form passes the flag through $options: db.users.find({ name: { $regex: "^ja", $options: "i" } }).
With i, the pattern ^ja still matches Jane Smith, Jack Johnson, and James Brown, and it would also match stored spellings such as jane smith or JACK JOHNSON. Keep the case-sensitive form when the case of the prefix is meaningful, because it behaves better with indexes, as the next section explains.
Use Indexes and Understand Performance
Anchored prefix patterns are the one regular-expression shape MongoDB can evaluate efficiently with an ordinary index. For a case-sensitive query such as db.users.find({ name: /^Ja/ }), MongoDB can turn the prefix into a bounded range over an index on name — roughly the values between Ja and Jb — instead of testing the pattern against every document. The ^ anchor is exactly what makes this index use possible; it does not prevent optimization.
Two qualifications matter:
- The
ioption defeats this optimization.$regexis not collation-aware, so a case-insensitive pattern cannot use an index effectively under any collection collation:db.users.find({ name: /^ja/i })falls back to scanning every candidate value even whennameis indexed. When case-insensitive prefix lookups need index support, a common workaround is to store a normalized lowercase copy of the field and query it with an anchored case-sensitive pattern; a case-insensitive collation can also help, but only for non-regex equality or range predicates, not for$regex. - Unanchored patterns such as
/Ja/cannot use a prefix range at all; MongoDB must test the expression against every candidate value.
For a collection queried by prefix often, create an index on the field with db.users.createIndex({ name: 1 }), keep the pattern anchored and case-sensitive where the data allows, and confirm the chosen plan with db.users.find(...).explain("executionStats") — the winning plan should show an IXSCAN over the field rather than a full COLLSCAN. On a very small collection the optimizer may still pick a scan because it is cheaper, and that is fine; the anchored prefix form is what gives MongoDB the option to use the index when it matters.