Consultas con regex y coincidencia de patrones
Aplicará expresiones regulares a campos de texto para realizar búsquedas flexibles por patrones.
Consultas con regex y coincidencia de patrones es una lección gratuita de MongoDB Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de MongoDB Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de MongoDB Academy incluye 4 lecciones en total.
Partes de esta lección aún no han sido traducidas y se muestran en inglés.
When You Need Pattern Matching
Sometimes you need to search for documents where a string field contains, starts with, or ends with a certain pattern—but you do not know the exact value. Simple equality filters like { name: 'Alice' } only match exact strings. Regular expressions (regex) give you flexible pattern matching against string fields in MongoDB.
MongoDB supports regex through the $regex operator or by passing a JavaScript regex literal directly in a query filter. Both approaches work, with slightly different syntax for setting options like case-insensitivity.
Basic Regex Syntax in MongoDB
There are two ways to use regex in MongoDB queries:
- JS regex literal:
{ name: /alice/i }— concise, flags go after the closing slash - $regex operator:
{ name: { $regex: 'alice', $options: 'i' } }— more verbose but required when combining with other operators
Both forms produce identical results. Use the JS literal syntax for simple queries; use the $regex operator form when you need to build the pattern dynamically from a string variable or combine it with other operators on the same field.
// JS regex literal - concise
db.users.find({ name: /alice/i });
// 'i' flag = case-insensitive
// $regex operator - equivalent
db.users.find({ name: { $regex: 'alice', $options: 'i' } });
// Dynamic pattern from variable:
const searchTerm = req.query.name;
const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special chars
db.users.find({ name: { $regex: escapedTerm, $options: 'i' } });Regex Options: i, m, s, x
MongoDB supports four regex option flags:
i— Case-insensitive:/alice/imatches 'Alice', 'ALICE', 'alice'm— Multiline:^and$match the start/end of each line rather than the whole strings— Dot-all:.matches any character including newlinesx— Extended: whitespace in the pattern is ignored (for readable patterns with comments)
The most commonly used flag is i. The m flag is useful for searching multi-line text fields like blog content. Multiple flags can be combined: { $options: 'im' }.
// Case-insensitive search for 'javascript'
db.courses.find({ title: { $regex: 'javascript', $options: 'i' } });
// Matches: 'JavaScript', 'JAVASCRIPT', 'javascript', 'JavaScript Tutorial'
// Multiline match: ^ anchors to start of each line
db.articles.find({ content: { $regex: '^Introduction', $options: 'm' } });
// Matches articles where any line starts with 'Introduction'
// Combined flags
db.posts.find({ body: { $regex: 'mongodb', $options: 'si' } });
// Case-insensitive + dot matches newlines in bodyAnchors: Starts With and Ends With
Use regex anchors to match the start or end of a string field:
^anchors to the start:/^Admin/matches strings that begin with 'Admin'$anchors to the end:/\.pdf$/matches strings ending with '.pdf'
A critical performance fact: a prefix regex with a caret (/^prefix/) CAN use a regular B-tree index on that field—MongoDB can seek directly to the prefix in the index. This makes prefix searches much faster than mid-string searches. Never use a leading wildcard (/.*pattern/ or /pattern/ without ^) on a large collection without a text index.
// Prefix match - CAN use index (very efficient)
db.users.find({ username: /^admin/i });
// Matches: 'admin', 'administrator', 'Admin123'
// Uses the index on username (if it exists)
// Suffix match - CANNOT use regular index (slower)
db.files.find({ filename: /\.pdf$/i });
// Matches: 'report.pdf', 'invoice.PDF'
// Must scan all documents - add text index if used frequently
// Mid-string - CANNOT use index
db.products.find({ description: /wireless/i });
// Must scan all documents - use $text index for thisCharacter Classes and Quantifiers
Regex gives you expressive pattern primitives:
.— any character (except newline, unlesssflag set)[abc]— character class: matches a, b, or c[a-z]— range: any lowercase letter\d— any digit (equivalent to[0-9])\w— any word character ([a-zA-Z0-9_])*,+,?— zero or more, one or more, zero or one{n},{n,m}— exactly n, between n and m occurrences
// Phone number pattern: +1-XXX-XXX-XXXX or similar
db.users.find({ phone: /^\+?\d{1,3}[-. ]?\(?\d{3}\)?[-. ]?\d{3}[-. ]?\d{4}$/ });
// 6-character alphanumeric codes
db.coupons.find({ code: /^[A-Z0-9]{6}$/ });
// Matches: 'SALE99', 'DISC25', 'FREE01'
// Email basic validation
db.users.find({ email: { $regex: '^[\\w.]+@[\\w.]+\\.[a-z]{2,}$', $options: 'i' } });Regex vs Text Index: Know the Difference
Regex queries and MongoDB's $text operator serve different purposes and have very different performance characteristics:
- Regex: matches by character pattern. Works on any string field, no special index needed (though prefix anchors use B-tree indexes). Suitable for format validation, prefix search, or pattern matching on small collections or indexed prefix queries.
- $text / text index: full-text keyword search with tokenization, stemming, and stop-word filtering. Requires a text index. Much faster for keyword search in large text fields (articles, descriptions, comments).
Never use /.*keyword.*/i on a large unindexed collection—it is a full scan and may be slow.
// Use REGEX for: format matching, prefix searches on indexed field
db.orders.find({ orderNumber: /^ORD-2024/ }); // Prefix - can use index
// Use $text for: keyword search in content fields
// First: create a text index
db.articles.createIndex({ content: 'text', title: 'text' });
// Then: full-text search
db.articles.find({ $text: { $search: 'mongodb performance' } });
// Much faster than /mongodb.*performance/i on large collectionsReDoS: The Security Risk
ReDoS (Regular Expression Denial of Service) is an attack where a malicious user crafts an input string that causes a poorly written regex to take exponential time to evaluate. If you pass user input directly into a regex without escaping, an attacker can hang your database query.
Always escape user input before using it in a regex by replacing all special regex characters (. * + ? ^ $ { } ( ) [ ] | \ ) with their escaped equivalents. Many libraries (like escape-string-regexp in Node.js) do this automatically. Additionally, prefer $text for user-facing search inputs over raw regex.
// DANGEROUS: raw user input in regex (ReDoS risk)
const input = req.query.search; // User controls this
db.products.find({ name: { $regex: input } }); // NEVER DO THIS
// SAFE: escape user input before using in regex
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const safeInput = escapeRegex(req.query.search);
db.products.find({ name: { $regex: safeInput, $options: 'i' } });
// BETTER: Use $text for user-facing search
db.products.find({ $text: { $search: req.query.search } });Regex on Array Fields
When you apply a regex to an array field, MongoDB checks whether any element of the array matches the pattern—the same containment semantics as equality queries on arrays. This lets you search through arrays of tags, categories, or any string array without a special operator.
For example, a document with tags: ['node.js', 'mongodb', 'backend'] would be returned by { tags: /^mongo/ } because 'mongodb' starts with 'mongo'. The regex is applied to each element independently.
// Document: { tags: ['node.js', 'mongodb', 'backend-dev'] }
// Find products where any tag starts with 'mongo'
db.products.find({ tags: /^mongo/i });
// Returns the document (tags contains 'mongodb')
// Find articles where any category contains 'tech'
db.articles.find({ categories: /tech/i });
// Matches: categories containing 'technology', 'tech-news', 'fintech'
// Index on array field improves regex prefix searches
db.articles.createIndex({ categories: 1 });Practical Search Example
A typical e-commerce search feature combines regex with other filters to provide a contextual, case-insensitive product search. The query matches product names that contain the search term anywhere in the string, filtered by category and in-stock status.
For small catalogs (under 50,000 products), regex search is acceptable. For larger catalogs or full-description search, Atlas Search (Lucene-based) provides superior relevance ranking, stemming, and performance.
// Search endpoint: GET /products?q=wireless&category=Electronics
app.get('/products', async (req, res) => {
const filter = { stock: { $gt: 0 } };
if (req.query.q) {
const escaped = req.query.q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
filter.name = { $regex: escaped, $options: 'i' };
}
if (req.query.category) {
filter.category = req.query.category;
}
const products = await db.collection('products')
.find(filter)
.project({ name: 1, price: 1, _id: 1 })
.limit(50)
.toArray();
res.json(products);
});Regex Performance Summary
Key rules for regex performance in MongoDB:
- Prefix with
^(/^prefix/): Can use a B-tree index. Best performance for regex. - Case-sensitive prefix (
/^prefix/): Fully exploits index ordering. - Case-insensitive prefix (
/^prefix/i): Partially uses index but still much faster than no anchor. - Contains without anchor (
/pattern/): Full collection scan—use text index instead. - Suffix (
/pattern$/): Full collection scan or text index.
When in doubt, test with explain('executionStats') and look for IXSCAN vs COLLSCAN.
// Check if regex query uses an index
db.users.find({ username: /^alice/i })
.explain('executionStats');
// winningPlan.stage should be 'IXSCAN' if username is indexed
// Compare index scan vs collection scan:
// /^alice/ on indexed field: totalDocsExamined ~= nReturned (efficient)
// /alice/ on any field: totalDocsExamined = all documents (slow!)Testing Regex Patterns Before Deployment
Before running a regex query on a production collection, test the pattern against sample documents to verify it matches what you intend and does not match what you do not intend. The MongoDB shell lets you test quickly with a small limit(), and JavaScript's String.prototype.test() or regex literals let you validate patterns in Node.js before embedding them in queries.
Also check performance with explain(): a regex that requires a full collection scan should be converted to a text query or have its collection size considered. For new collections, design with search requirements in mind—add text indexes from the start rather than retrofitting them.
// Step 1: Test regex in Node.js before using in query
const pattern = /^wireless/i;
const testStrings = ['Wireless Headphones', 'wireless mouse', 'Wired Keyboard'];
testStrings.forEach(s => console.log(s, '=>', pattern.test(s)));
// 'Wireless Headphones' => true
// 'wireless mouse' => true
// 'Wired Keyboard' => false
// Step 2: Test on production with limit
db.products.find({ name: /^wireless/i }).limit(5);
// Step 3: Check performance
db.products.find({ name: /^wireless/i }).explain('executionStats');Quick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: regex queries use /pattern/flags or $regex operator for flexible string pattern matching—the most important flag is i for case-insensitivity, prefix-anchored regexes (/^prefix/) can use B-tree indexes for efficient lookups while mid-string patterns require full scans, and always escape user input before inserting it into a regex to prevent ReDoS attacks—or better yet, use the $text operator with a text index for user-facing search. Next up we move into updating documents with $set, $unset, and other update operators.
Preguntas frecuentes
¿La lección «Consultas con regex y coincidencia de patrones» es gratis?
Sí — el texto completo de «Consultas con regex y coincidencia de patrones» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de MongoDB Academy, actualiza a CoddyKit PRO. El curso de MongoDB Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Consultas con regex y coincidencia de patrones»?
Aplicará expresiones regulares a campos de texto para realizar búsquedas flexibles por patrones. Practicas MongoDB Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar MongoDB Academy?
No se requiere experiencia previa. MongoDB Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Consultas con regex y coincidencia de patrones»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de MongoDB Academy?
Sí. Cada lección de MongoDB Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Operadores de comparación: $eq, $gt, $lt, $in
- Operadores lógicos: $and, $or, $nor, $not
- Operadores de elementos y comprobaciones de tipos
- Consultas con regex y coincidencia de patrones