Si trabajas con MongoDB, una de las primeras cosas que necesitas es ver qué colecciones tienes en tu base de datos. Parece algo trivial, ¿verdad? Pero en la shell de Mongo hay al menos dos formas de hacerlo, y la diferencia entre ellas es clave si no quieres toparte con errores raros más adelante. Yo siempre veo cómo la gente se complica por no entender esto bien.
Dos formas de listar colecciones
Por un lado, tienes el comando más conocido:
show collections
Este es un helper del shell de MongoDB. Lo escribes, le das enter, y te muestra la lista de colecciones de forma bonita, con un formato que es fácil de leer para nosotros los humanos. Es súper práctico cuando estás explorando una base de datos directamente en la consola.
Por el otro, tenemos una función de JavaScript que hace lo mismo:
db.getCollectionNames()
Esta función, a diferencia del show collections, devuelve un array de strings con los nombres de las colecciones. También es directo, pero su naturaleza es distinta: es una función que puedes llamar como cualquier otra en un contexto JavaScript.
¿Por qué importa la diferencia? El drama del --eval
Aquí es donde la cosa se pone interesante. Si solo usas la shell de forma interactiva, ambos métodos funcionan bien. ¿Pero qué pasa si quieres ejecutar un comando de Mongo desde la línea de comandos, sin entrar a la shell interactiva? Por ejemplo, para un script o automatización. Ahí es donde entra el flag --eval.
Si intentas usar show collections con --eval, es probable que te encuentres con un error como este:
$ mongo prodmongo/app --eval "show collections"
MongoDB shell version: 3.2.10
connecting to: prodmongo/app
2016-10-26T19:34:34.886-0400 E QUERY [thread1] SyntaxError: missing ; before statement @(shell eval):1:5
¿Por qué? Porque show collections no es una expresión JavaScript válida por sí misma. Es un comando especial que entiende el shell de Mongo, no un trozo de JavaScript ejecutable. Me costó entender esto al principio, igual que a muchos. De hecho, esta es una de las frustraciones que me provoca la sobreingeniería o las capas de abstracción innecesarias: algo simple se vuelve complejo por cómo se implementa.
En cambio, con db.getCollectionNames(), que sí es una función JavaScript, no tendrás ningún problema:
$ mongo prodmongo/app --eval "db.getCollectionNames()"
MongoDB shell version: 3.2.10
connecting to: prodmongo/app
[
"Profiles",
"Unit_Info"
]
Para mí, esta es la forma de hacerlo si vas a trabajar con scripts. Es más robusta y predecible. Yo prefiero usar db.getCollectionNames() en la mayoría de los casos, incluso de forma interactiva, porque me acostumbro a la sintaxis que sé que funcionará en cualquier contexto programático.
Ojo con la automatización
La mayor equivocación que veo es que la gente asume que todos los comandos que funcionan en la shell interactiva son equivalentes a funciones JavaScript. No es así. Cuando necesites automatizar tareas o ejecutar comandos de MongoDB desde un script, siempre piensa en usar las funciones de la API de JavaScript (db.getCollectionNames(), db.collection.find(), etc.) en lugar de los shell helpers más "amigables". Te evitará errores de sintaxis y la necesidad de buscar workarounds innecesarios. Mantenerlo simple y funcional es mi mantra.