HOWTO · MongoDB
MongoDB comienza con consulta
En este artículo de MongoDB, el usuario aprenderá cómo hacer una consulta que comienza con $regex. Proporciona capacidades de expresión regular para cadenas de coincidencia de patrones en consultas.
En esta página
Una tarea habitual en MongoDB es encontrar todos los documentos en los que un campo de cadena empieza por un prefijo elegido; por ejemplo, todos los usuarios cuyo name empieza por Ja. MongoDB no tiene un operador startsWith específico, por lo que la solución estándar es una expresión regular anclada al principio de la cadena, escrita con el operador $regex o como un literal de expresión regular en el filtro de la consulta.
Los fragmentos de consulta de esta página usan la sintaxis de mongosh, que se ejecuta en MongoDB Shell o en una sesión de driver equivalente, no en un shell del sistema; ejecútalos contra tu propio despliegue para ver resultados en vivo. El script ejecutable que aparece más abajo reproduce la misma lógica de coincidencia en JavaScript puro.
Usa un $regex anclado para coincidencias de prefijo
Una coincidencia de «empieza por» es una coincidencia de patrón en la que el ancla ^ fija el patrón al primer carácter de la cadena. El patrón /^Ja/ solo coincide con valores cuyos dos primeros caracteres son Ja; un valor que simplemente contiene Ja más adelante, como McJane, no coincide. Sin ^, el patrón /Ja/ recorre toda la cadena y coincide con Ja en cualquier posición, lo que convierte una consulta de prefijo en una consulta de «contiene».
La forma con el operador $regex de una consulta de «empieza por» es db.collection.find({ name: { $regex: "^Ja" } }), donde:
db.collectiones la colección en la que buscar.namees el campo de cadena que se va a comprobar.$regexindica a MongoDB que evalúe el valor como una expresión regular."^Ja"es el patrón:^lo ancla al principio de la cadena yJaes el prefijo literal.
En mongosh y en los drivers que admiten literales de expresión regular, puedes escribir el mismo filtro de forma más compacta como db.users.find({ name: /^Ja/ }).
Como el patrón es una expresión regular y no una cadena simple, un prefijo que contenga metacaracteres de regex como ., *, +, (, ), [, ] o $ debe escaparse con una barra invertida. Por ejemplo, el prefijo literal v1. necesita el patrón "^v1\\."; si no se escapa, el . coincide con cualquier carácter y la consulta deja de comportarse como una coincidencia de prefijo literal.
Ejecuta una consulta de «empieza por»
Supón que una colección users contiene documentos cuyos valores de name son John Doe, Jane Smith, Jack Johnson, Jill Jackson y James Brown, insertados, por ejemplo, con db.users.insertMany([{ name: "John Doe" }, { name: "Jane Smith" }, { name: "Jack Johnson" }, { name: "Jill Jackson" }, { name: "James Brown" }]).
La consulta db.users.find({ name: { $regex: "^Ja" } }) devuelve los documentos cuyo name empieza por Ja: Jane Smith, Jack Johnson y James Brown. John Doe empieza por Jo y Jill Jackson empieza por Ji, así que el ancla excluye ambos.
mongosh acepta literales de expresión regular al estilo de JavaScript, como /^Ja/, pero el servidor evalúa $regex con un motor compatible con PCRE, no con JavaScript. Para este patrón anclado, las semánticas coinciden, por lo que el siguiente script reproduce la misma lógica de coincidencia en JavaScript puro y puedes confirmar qué documentos selecciona:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
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
Elige una coincidencia sensible o insensible a mayúsculas y minúsculas
La coincidencia de expresiones regulares en MongoDB distingue mayúsculas de minúsculas por defecto, así que ^Ja no coincide con un valor como james brown. Para hacer coincidir un prefijo sin distinguir mayúsculas, añade la opción i, escrita como db.users.find({ name: /^ja/i }). La forma equivalente con $regex pasa el indicador a través de $options: db.users.find({ name: { $regex: "^ja", $options: "i" } }).
Con i, el patrón ^ja sigue coincidiendo con Jane Smith, Jack Johnson y James Brown, y también coincidiría con grafías almacenadas como jane smith o JACK JOHNSON. Conserva la forma sensible a mayúsculas cuando el uso de mayúsculas del prefijo sea significativo, porque funciona mejor con los índices, como explica la siguiente sección.
Usa índices y comprende el rendimiento
Los patrones de prefijo anclados son la única forma de expresión regular que MongoDB puede evaluar eficientemente con un índice ordinario. Para una consulta sensible a mayúsculas como db.users.find({ name: /^Ja/ }), MongoDB puede convertir el prefijo en un rango acotado sobre un índice en name —aproximadamente los valores entre Ja y Jb— en lugar de comprobar el patrón contra cada documento. El ancla ^ es exactamente lo que hace posible este uso del índice; no impide la optimización.
Dos matices importan:
- La opción
ianula esta optimización.$regexno tiene en cuenta la intercalación, por lo que un patrón insensible a mayúsculas no puede usar un índice eficazmente con ninguna intercalación de colección:db.users.find({ name: /^ja/i })recurre a examinar cada valor candidato incluso cuandonameestá indexado. Cuando las búsquedas por prefijo insensibles a mayúsculas necesitan soporte de índice, una solución habitual es almacenar una copia normalizada en minúsculas del campo y consultarla con un patrón anclado sensible a mayúsculas; una intercalación insensible a mayúsculas también puede ayudar, pero solo para predicados de igualdad o rango que no sean regex, no para$regex. - Los patrones no anclados como
/Ja/no pueden usar en absoluto un rango de prefijo; MongoDB debe probar la expresión contra cada valor candidato.
Para una colección consultada por prefijo con frecuencia, crea un índice en el campo con db.users.createIndex({ name: 1 }), mantén el patrón anclado y sensible a mayúsculas cuando los datos lo permitan y confirma el plan elegido con db.users.find(...).explain("executionStats"): el plan ganador debe mostrar un IXSCAN sobre el campo en lugar de un COLLSCAN completo. En una colección muy pequeña, el optimizador aún puede elegir un examen porque resulta más barato, y eso está bien; la forma de prefijo anclado es lo que da a MongoDB la opción de usar el índice cuando importa.