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.
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.
Respuestas:
No existe un método para eliminar una colección de mangosta, lo mejor que puede hacer es eliminar el contenido de una:
Model.remove({}, function(err) {
console.log('collection removed')
});
Pero hay una forma de acceder al controlador javascript nativo de mongodb, que se puede usar para esto
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
Haga una copia de seguridad antes de intentar esto en caso de que algo salga mal.
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();
});
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 de connect
, as mongoose.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
//CoffeeScript
mongoose = require "mongoose"
conn = mongoose.connect("mongodb://localhost/mydb")
conn.connection.db.dropDatabase()
//JavaScript
var conn, mongoose;
mongoose = require("mongoose");
conn = mongoose.connect("mongodb://localhost/mydb");
conn.connection.db.dropDatabase();
HTH al menos lo hizo por mí, así que decidí compartir =)
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
realidad devuelve mongoose
. En lugar de conn = mongoose.connect(...)
escribir mongoose.connect(...)
y luego conn = 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 el dropDatabase
comando en la devolución de llamada a la connect
declaración o un open
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í.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
con.connection.db.dropDatabase(function(err, result){
done();
});
});
Puede leer más https://github.com/Automattic/mongoose/issues/1469
Una respuesta actualizada, para 4.6.0+, si tiene preferencia por las promesas ( consulte los documentos ):
mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
connection.db.dropDatabase();
// alternatively:
// mongoose.connection.db.dropDatabase();
});
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:
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')
})
})
})
Para vaciar una colección en particular en una base de datos:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
Nota:
Esto funciona para mí a partir de Mongoose v4.7.0
:
mongoose.connection.dropDatabase();
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 dropDatabase
comando en el open
controlador. Pero eso solo funciona en el caso de que la conexión aún no esté abierta.
Connection.prototype.dropDatabase = function(callback) {
var Promise = PromiseProvider.get();
var _this = this;
var promise = new Promise.ES6(function(resolve, reject) {
if (_this.readyState !== STATES.connected) {
_this.on('open', function() {
_this.db.dropDatabase(function(error) {
if (error) {
reject(error);
} else {
resolve();
}
});
});
} else {
_this.db.dropDatabase(function(error) {
if (error) {
reject(error);
} else {
resolve();
}
});
}
});
if (callback) {
promise.then(function() { callback(); }, callback);
}
return promise;
};
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);
}
}
Mangosta 4.6.0+:
mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
mongoose.connection.db.dropDatabase();
});
Pasar una devolución de llamada para conectarse ya no funcionará:
TypeError: no se puede leer la propiedad 'commandsTakeWriteConcern' de null
connect
devuelve una promesa, por lo que puede agregar .then((connection) => { ... });
al mongoose.connect
. Ver: mongoosejs.com/docs/connections.html
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.
Model.deleteMany();
Esto eliminará todo el contenido de este modelo en particular y su colección estará vacía.