Come eliminare un database con Mongoose?


Risposte:


166

Non esiste un metodo per eliminare una raccolta da mangusta, il meglio che puoi fare è rimuovere il contenuto di uno:

Model.remove({}, function(err) { 
   console.log('collection removed') 
});

Ma c'è un modo per accedere al driver javascript nativo di mongodb, che può essere utilizzato per questo

mongoose.connection.collections['collectionName'].drop( function(err) {
    console.log('collection dropped');
});

avvertimento

Fai un backup prima di provarlo nel caso qualcosa vada storto!


2
quando provo la seconda opzione ottengo "impossibile leggere la proprietà 'collectionName' di undefined"
Yaron Naveh

1
Dato che tutte le raccolte si trovano nell'hash mongoose.connection.collections, potresti semplicemente elencarle per (collection in mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ... smth similar
drinchev

3
Hai un errore di battitura - una virgola in più dopo la funzione (err) ... dovrebbe essere: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
arxpoetica

3
Sono l'unico che ha realizzato che questa risposta non affronta la domanda su come eliminare un database. Non sta chiedendo di rilasciare una collezione, sta chiedendo di cancellare un database ..
Joseph Persie

3
"Non esiste un metodo per eliminare una raccolta da mangusta", prima di tutto l'OP vuole eliminare un database, non una raccolta, secondo la risposta di @hellslam sotto funziona bene.
SCBuergel.eth

79

Mongoose creerà un database se non ne esiste già uno sulla connessione, quindi una volta stabilita la connessione, puoi semplicemente interrogarlo per vedere se c'è qualcosa al suo interno.

Puoi rilasciare qualsiasi database a cui sei connesso:

var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
    /* Drop the DB */
    mongoose.connection.db.dropDatabase();
});

1
Ho provato mongoose.connection.db.dropDatabase()ma ho trovato il db c'è ancora? Mi manca qualcosa?
Freewind

Se ti connetti ad esso in seguito verrebbe ricreato, sebbene vuoto. C'erano delle raccolte dopo che l'hai lasciato cadere?
hellslam

Stai usando la stessa connessione dappertutto o stai creando più connessioni?
hellslam

12
Ho scoperto che l' dropDatabaseinvocazione dovrebbe essere inserita nella richiamata di connect, as mongoose.connect('...', function() { ...dropDatabase()}).
Freewind

1
dropDatabase sembra non funzionare in alcuni casi, ma il comando mongo diretto può ancora essere utilizzato mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz

14

Se modifichi la soluzione di @ hellslam in questo modo, funzionerà

Uso questa tecnica per eliminare il database dopo i miei test di integrazione

//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 almeno ha fatto per me, quindi ho deciso di condividere =)


è possibile eliminare db con questo? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy

2
Questo è stato utile, grazie! Tuttavia, i nomi delle variabili sono un po 'fuorvianti ... in mongoose.connectrealtà restituisce mongoose. Invece di conn = mongoose.connect(...)scrivere mongoose.connect(...)e poi conn = mongooose.connection.
un nerd pagato il

Non penso che questo codice funzionerà sempre perché connectè asincrono. Quindi, se la connessione non avviene immediatamente, il comando dropDatabase () fallirà. Ecco perché le altre soluzioni precedenti consigliavano di inserire il dropDatabasecomando nel callback connectdell'istruzione o di un opengestore di eventi.
Mark Stosberg

8

Ho provato le risposte di @ hellslam e @ silverfighter. Ho trovato una condizione di gara che ha frenato i miei test. Nel mio caso sto eseguendo test mocha e nella funzione before del test voglio cancellare l'intero DB. Ecco cosa funziona per me.

var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
    con.connection.db.dropDatabase(function(err, result){
        done();
    });
});

Puoi leggere di più https://github.com/Automattic/mongoose/issues/1469


7

Una risposta aggiornata, per 4.6.0+, se preferisci le promesse ( vedi documenti ):

mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
   connection.db.dropDatabase();
   // alternatively:
   // mongoose.connection.db.dropDatabase();
});

Ho testato questo codice nel mio codice, usando mongoose 4.13.6. Inoltre, nota l'uso useMongoClientdell'opzione ( vedi documenti ). I documenti indicano:

La logica di connessione predefinita di Mongoose è deprecata a partire dalla 4.11.0. Si prega di aderire alla nuova logica di connessione utilizzando l'opzione useMongoClient, ma assicurarsi di testare prima le connessioni se si aggiorna una base di codice esistente!


5

La difficoltà che ho avuto con le altre soluzioni è che si basano sul riavvio dell'applicazione se si desidera ripristinare il funzionamento degli indici.

Per le mie esigenze (ovvero poter eseguire uno unit test delle bombe su tutte le raccolte, quindi ricrearle insieme ai loro indici), ho finito per implementare questa soluzione:

Questo si basa sulle librerie underscore.js e async.js per assemblare gli indici in parallelo, potrebbe essere risolto se sei contrario a quella libreria, ma lo lascio come esercizio per lo sviluppatore.

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

4

Per svuotare una particolare raccolta in un database:

model.remove(function(err, p){
    if(err){ 
        throw err;
    } else{
        console.log('No Of Documents deleted:' + p);
    }
});

Nota:

  1. Scegli un modello che fa riferimento a uno schema particolare (schema di raccolta che desideri eliminare).
  2. Questa operazione non eliminerà il nome della raccolta dal database.
  3. Questo elimina tutti i documenti in una raccolta.

4

Questo funziona per me a partire da Mongoose v4.7.0:

mongoose.connection.dropDatabase();

4

Il modo migliore per inserire il database in Mongoose dipende dalla versione di Mongoose che stai utilizzando. Se stai utilizzando una versione di Mongoose 4.6.4 o successiva, è probabile che questo metodo aggiunto in quella versione funzionerà bene per te:

mongoose.connection.dropDatabase();

Nelle versioni precedenti questo metodo non esisteva. Invece, dovevi usare una chiamata MongoDB diretta:

mongoose.connection.db.dropDatabase();

Tuttavia, se questo è stato eseguito subito dopo la creazione della connessione al database, potrebbe non riuscire silenziosamente. Ciò è correlato alla connessione effettivamente asincrona e non ancora configurata quando viene eseguito il comando. Questo normalmente non è un problema per altre chiamate Mongoose come.find() , che si accodano fino a quando la connessione non è aperta e quindi vengono eseguite.

Se guardi il codice sorgente di dropDatabase() collegamento che è stato aggiunto, puoi vedere che è stato progettato per risolvere esattamente questo problema. Verifica se la connessione è aperta e pronta. In tal caso, attiva immediatamente il comando. In caso contrario, registra il comando da eseguire quando la connessione al database è stata aperta.

Alcuni dei suggerimenti precedenti consigliano di inserire sempre il dropDatabasecomando nel opengestore. Ma ciò funziona solo nel caso in cui la connessione non sia ancora aperta.

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

Ecco una versione semplice della logica precedente che può essere utilizzata con le versioni precedenti di 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);
    }
}  

2

Mangusta 4.6.0+:

mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
    mongoose.connection.db.dropDatabase();
});

Passare una richiamata per connettersi non funzionerà più:

TypeError: Impossibile leggere la proprietà "commandsTakeWriteConcern" di null


1
connectrestituisce una promessa, quindi puoi aggiungerla .then((connection) => { ... });al file mongoose.connect. Vedi: 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()
    })
  })

0

Poiché il metodo remove è sconsigliato nella libreria mongoose, possiamo usare la funzione deleteMany senza che vengano passati parametri.

Model.deleteMany();

Questo cancellerà tutto il contenuto di questo particolare modello e la tua collezione sarà vuota.


0

Per rilasciare tutti i documenti in una raccolta:

await mongoose.connection.db.dropDatabase();

Questa risposta è basata sul file mongoose index.d.ts:

dropDatabase(): Promise<any>;

-2

Per rilasciare tutti i documenti in una raccolta:

myMongooseModel.collection.drop();

come si è visto nei test

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.