Estoy preparando un script de creación de base de datos en Node.js y Mongoose. ¿Cómo puedo verificar si la base de datos ya existe y, de ser así, eliminarla (eliminarla) usando Mongoose?
No pude encontrar una manera de dejarlo con Mongoose.
cuando intento la segunda opción, obtengo "no se puede leer la propiedad 'collectionName' de undefined"
Yaron Naveh
1
Dado que todas las colecciones están en el hash mongoose.connection.collections, puede simplemente enumerarlas para (colección en mongoose.connection.collections) {mongoose.connection.collections [colección] .drop} ... algo similar
drinchev
3
Tiene un error tipográfico: una coma adicional después de la función (err) ... debería ser: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
arxpoetica
3
¿Soy el único que se dio cuenta de que esta respuesta no aborda la cuestión de cómo eliminar una base de datos? No está pidiendo que suelte una colección, está pidiendo que suelte una base de datos ..
Joseph Persie
3
"No hay un método para eliminar una colección de mangosta", en primer lugar, el OP quiere eliminar una base de datos, no una recopilación, en segundo lugar, la respuesta de @hellslam a continuación funciona bien.
SCBuergel.eth
79
Mongoose creará una base de datos si aún no existe una en la conexión, por lo que una vez que realice la conexión, puede consultarla para ver si hay algo en ella.
Puede eliminar cualquier base de datos a la que esté conectado:
var mongoose = require('mongoose');/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){/* Drop the DB */
mongoose.connection.db.dropDatabase();});
Lo intenté mongoose.connection.db.dropDatabase()pero encontré que la base de datos todavía está allí. ¿Me pierdo algo?
Freewind
Si se conecta a él después, se volverá a crear, aunque vacío. ¿Había colecciones en él después de que lo dejó?
hellslam
¿Está utilizando la misma conexión en todo momento o está creando varias conexiones?
hellslam
12
Encontré que la dropDatabaseinvocación debería colocarse en la devolución de llamada de connect, as mongoose.connect('...', function() { ...dropDatabase()}).
Freewind
1
dropDatabase parece no funcionar en algunos casos, pero el comando directo de mongo aún se puede usar mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz
14
Si modifica la solución de @ hellslam de esta manera, funcionará
Utilizo esta técnica para eliminar la base de datos después de mis pruebas de integración
¿Es posible eliminar db con esto? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
Chovy
2
¡Esto fue útil, gracias! Sin embargo, los nombres de sus variables son un poco engañosos ... en mongoose.connectrealidad devuelve mongoose. En lugar de conn = mongoose.connect(...)escribir mongoose.connect(...)y luego conn = mongooose.connection.
un nerd pagado
No creo que este código siempre funcione porque connectes asincrónico. Entonces, si la conexión no ocurre de inmediato, el comando dropDatabase () fallará. Es por eso que las otras soluciones anteriores recomendaron poner el dropDatabasecomando en la devolución de llamada a la connectdeclaración o un opencontrolador de eventos.
Mark Stosberg
8
Probé las respuestas de @hellslam y @ silverfighter. Encontré una condición de carrera que frenaba mis pruebas. En mi caso, estoy ejecutando pruebas de moca y en la función anterior de la prueba quiero borrar toda la base de datos. Esto es lo que funciona para mí.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open',function(){
con.connection.db.dropDatabase(function(err, result){
done();});});
Probé este código en mi propio código, usando mongoose 4.13.6. Además, tenga en cuenta el uso de la useMongoClientopción ( ver documentos ). Los documentos indican:
La lógica de conexión predeterminada de Mongoose está obsoleta a partir de 4.11.0. Opte por la nueva lógica de conexión utilizando la opción useMongoClient, pero asegúrese de probar sus conexiones primero si está actualizando una base de código existente.
La dificultad que he tenido con las otras soluciones es que se basan en reiniciar su aplicación si desea que los índices vuelvan a funcionar.
Para mis necesidades (es decir, poder ejecutar una prueba unitaria de todas las colecciones nucleares y luego recrearlas junto con sus índices), terminé implementando esta solución:
Esto se basa en las bibliotecas underscore.js y async.js para ensamblar los índices en paralelo, podría deshacerse si está en contra de esa biblioteca, pero lo dejo como ejercicio para el desarrollador.
mongoose.connection.db.executeDbCommand({dropDatabase:1},function(err, result){var mongoPath = mongoose.connections[0].host +':'+ mongoose.connections[0].port +'/'+ mongoose.connections[0].name//Kill the current connection, then re-establish it
mongoose.connection.close()
mongoose.connect('mongodb://'+ mongoPath,function(err){var asyncFunctions =[]//Loop through all the known schemas, and execute an ensureIndex to make sure we're clean
_.each(mongoose.connections[0].base.modelSchemas,function(schema, key){
asyncFunctions.push(function(cb){
mongoose.model(key, schema).ensureIndexes(function(){return cb()})})})async.parallel(asyncFunctions,function(err){
console.log('Done dumping all collections and recreating indexes')})})})
La mejor manera de colocar su base de datos en Mongoose depende de la versión de Mongoose que esté utilizando. Si está utilizando una versión de Mongoose 4.6.4 o más reciente, entonces este método agregado en esa versión probablemente funcionará bien para usted:
mongoose.connection.dropDatabase();
En versiones anteriores, este método no existía. En su lugar, debía utilizar una llamada directa a MongoDB:
mongoose.connection.db.dropDatabase();
Sin embargo, si esto se ejecutó justo después de que se creó la conexión a la base de datos, posiblemente podría fallar silenciosamente. Esto está relacionado con que la conexión sea realmente asíncrona y aún no se haya configurado cuando se ejecute el comando. Normalmente, esto no es un problema para otras llamadas de Mongoose .find(), que hacen cola hasta que la conexión se abre y luego se ejecuta.
Si observa el código fuente del dropDatabase()acceso directo que se agregó, puede ver que fue diseñado para resolver este problema exacto. Comprueba si la conexión está abierta y lista. Si es así, dispara el comando inmediatamente. De lo contrario, registra el comando que se ejecutará cuando se abra la conexión a la base de datos.
Algunas de las sugerencias anteriores recomiendan poner siempre su dropDatabasecomando en el opencontrolador. Pero eso solo funciona en el caso de que la conexión aún no esté abierta.
Aquí hay una versión simple de la lógica anterior que se puede usar con versiones anteriores de Mongoose:
// This shim is backported from Mongoose 4.6.4 to reliably drop a database// http://stackoverflow.com/a/42860208/254318// The first arg should be "mongoose.connection"function dropDatabase (connection, callback){// readyState 1 === 'connected'if(connection.readyState !==1){
connection.on('open',function(){
connection.db.dropDatabase(callback);});}else{
connection.db.dropDatabase(callback);}}
connectdevuelve una promesa, por lo que puede agregar .then((connection) => { ... });al mongoose.connect. Ver: mongoosejs.com/docs/connections.html
Andre M
1
beforeEach((done)=>{
mongoose.connection.dropCollection('products',(error ,result)=>{if(error){
console.log('Products Collection is not dropped')}else{
console.log(result)}
done()})})
Respuestas:
No existe un método para eliminar una colección de mangosta, lo mejor que puede hacer es eliminar el contenido de una:
Pero hay una forma de acceder al controlador javascript nativo de mongodb, que se puede usar para esto
Advertencia
Haga una copia de seguridad antes de intentar esto en caso de que algo salga mal.
fuente
Mongoose creará una base de datos si aún no existe una en la conexión, por lo que una vez que realice la conexión, puede consultarla para ver si hay algo en ella.
Puede eliminar cualquier base de datos a la que esté conectado:
fuente
mongoose.connection.db.dropDatabase()
pero encontré que la base de datos todavía está allí. ¿Me pierdo algo?dropDatabase
invocación debería colocarse en la devolución de llamada deconnect
, asmongoose.connect('...', function() { ...dropDatabase()})
.mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
Si modifica la solución de @ hellslam de esta manera, funcionará
Utilizo esta técnica para eliminar la base de datos después de mis pruebas de integración
HTH al menos lo hizo por mí, así que decidí compartir =)
fuente
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
realidad devuelvemongoose
. En lugar deconn = mongoose.connect(...)
escribirmongoose.connect(...)
y luegoconn = mongooose.connection
.connect
es asincrónico. Entonces, si la conexión no ocurre de inmediato, el comando dropDatabase () fallará. Es por eso que las otras soluciones anteriores recomendaron poner eldropDatabase
comando en la devolución de llamada a laconnect
declaración o unopen
controlador de eventos.Probé las respuestas de @hellslam y @ silverfighter. Encontré una condición de carrera que frenaba mis pruebas. En mi caso, estoy ejecutando pruebas de moca y en la función anterior de la prueba quiero borrar toda la base de datos. Esto es lo que funciona para mí.
Puede leer más https://github.com/Automattic/mongoose/issues/1469
fuente
Una respuesta actualizada, para 4.6.0+, si tiene preferencia por las promesas ( consulte los documentos ):
Probé este código en mi propio código, usando mongoose 4.13.6. Además, tenga en cuenta el uso de la
useMongoClient
opción ( ver documentos ). Los documentos indican:fuente
La dificultad que he tenido con las otras soluciones es que se basan en reiniciar su aplicación si desea que los índices vuelvan a funcionar.
Para mis necesidades (es decir, poder ejecutar una prueba unitaria de todas las colecciones nucleares y luego recrearlas junto con sus índices), terminé implementando esta solución:
Esto se basa en las bibliotecas underscore.js y async.js para ensamblar los índices en paralelo, podría deshacerse si está en contra de esa biblioteca, pero lo dejo como ejercicio para el desarrollador.
fuente
Para vaciar una colección en particular en una base de datos:
Nota:
fuente
Esto funciona para mí a partir de Mongoose
v4.7.0
:fuente
La mejor manera de colocar su base de datos en Mongoose depende de la versión de Mongoose que esté utilizando. Si está utilizando una versión de Mongoose 4.6.4 o más reciente, entonces este método agregado en esa versión probablemente funcionará bien para usted:
En versiones anteriores, este método no existía. En su lugar, debía utilizar una llamada directa a MongoDB:
Sin embargo, si esto se ejecutó justo después de que se creó la conexión a la base de datos, posiblemente podría fallar silenciosamente. Esto está relacionado con que la conexión sea realmente asíncrona y aún no se haya configurado cuando se ejecute el comando. Normalmente, esto no es un problema para otras llamadas de Mongoose
.find()
, que hacen cola hasta que la conexión se abre y luego se ejecuta.Si observa el código fuente del
dropDatabase()
acceso directo que se agregó, puede ver que fue diseñado para resolver este problema exacto. Comprueba si la conexión está abierta y lista. Si es así, dispara el comando inmediatamente. De lo contrario, registra el comando que se ejecutará cuando se abra la conexión a la base de datos.Algunas de las sugerencias anteriores recomiendan poner siempre su
dropDatabase
comando en elopen
controlador. Pero eso solo funciona en el caso de que la conexión aún no esté abierta.Aquí hay una versión simple de la lógica anterior que se puede usar con versiones anteriores de Mongoose:
fuente
Mangosta 4.6.0+:
Pasar una devolución de llamada para conectarse ya no funcionará:
TypeError: no se puede leer la propiedad 'commandsTakeWriteConcern' de null
fuente
connect
devuelve una promesa, por lo que puede agregar.then((connection) => { ... });
almongoose.connect
. Ver: mongoosejs.com/docs/connections.htmlfuente
Dado que el método de eliminación está depreciado en la biblioteca de mangosta, podemos usar la función deleteMany sin pasar parámetros.
Esto eliminará todo el contenido de este modelo en particular y su colección estará vacía.
fuente
Para colocar todos los documentos en una colección:
Esta respuesta se basa en el archivo mongoose index.d.ts:
fuente
Para colocar todos los documentos en una colección:
como se ve en las pruebas
fuente