¿Cómo eliminar una base de datos con Mongoose?

97

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.

Yaron Naveh
fuente
Duplicado: stackoverflow.com/questions/11453617/…
Uday Hiwarale

Respuestas:

166

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');
});

Advertencia

Haga una copia de seguridad antes de intentar esto en caso de que algo salga mal.

Drinchev
fuente
2
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();
});
infierno
fuente
1
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

//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 =)

silverfighter
fuente
¿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();
    });
});

Puede leer más https://github.com/Automattic/mongoose/issues/1469

zafrani
fuente
7

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 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.

Andre M
fuente
5

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')
    })
  })
})
Eric Caron
fuente
4

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:

  1. Elija un modelo que se refiera a un esquema particular (esquema de colección que desea eliminar).
  2. Esta operación no eliminará el nombre de la colección de la base de datos.
  3. Esto elimina todos los documentos de una colección.
danés
fuente
4

Esto funciona para mí a partir de Mongoose v4.7.0:

mongoose.connection.dropDatabase();
usuario3344977
fuente
4

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.

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);
    }
}  
Mark Stosberg
fuente
2

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

Rayjax
fuente
1
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()
    })
  })
Revt A
fuente
0

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.

SAYAM.S SANGHVI
fuente
0

Para colocar todos los documentos en una colección:

await mongoose.connection.db.dropDatabase();

Esta respuesta se basa en el archivo mongoose index.d.ts:

dropDatabase(): Promise<any>;
mrhid3f
fuente
-2

Para colocar todos los documentos en una colección:

myMongooseModel.collection.drop();

como se ve en las pruebas

Sgnl
fuente