Wie lösche ich eine Datenbank mit Mongoose?

97

Ich bereite ein Datenbankerstellungsskript in Node.js und Mongoose vor. Wie kann ich überprüfen, ob die Datenbank bereits vorhanden ist, und wenn ja, sie mit Mongoose löschen (löschen)?

Ich konnte keinen Weg finden, es mit Mungo fallen zu lassen.

Yaron Naveh
quelle

Antworten:

166

Es gibt keine Methode, um eine Sammlung von Mungos zu löschen. Das Beste, was Sie tun können, ist, den Inhalt einer Sammlung zu entfernen:

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

Es gibt jedoch eine Möglichkeit, auf den mongodb nativen Javascript-Treiber zuzugreifen, der dafür verwendet werden kann

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

Warnung

Erstellen Sie ein Backup, bevor Sie dies versuchen, falls etwas schief geht!

drinchev
quelle
2
Wenn ich die zweite Option versuche, erhalte ich die Meldung "Die Eigenschaft 'collectionName' von undefined kann nicht gelesen werden"
Yaron Naveh,
1
Da sich alle Sammlungen im Hash mongoose.connection.collections befinden, können Sie sie einfach auflisten für (Sammlung in mongoose.connection.collections) {mongoose.connection.collections [Sammlung] .drop} ... smth ähnlich
drinchev
3
Sie haben einen Tippfehler - ein zusätzliches Komma nach der Funktion (err) ... sollte lauten: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
Arxpoetica
3
Bin ich der einzige, der diese Antwort erkannt hat, geht nicht auf die Frage ein, wie eine Datenbank gelöscht werden soll. Es geht nicht darum, eine Sammlung zu löschen, sondern darum, eine Datenbank
Joseph Persie
3
"Es gibt keine Methode, um eine Sammlung von Mungo zu löschen", erstens möchte das OP eine Datenbank löschen, keine Sammlung, zweitens funktioniert die Antwort von @hellslam unten gut.
SCBuergel.eth
79

Mongoose erstellt eine Datenbank, falls in der Verbindung noch keine vorhanden ist. Sobald Sie die Verbindung hergestellt haben, können Sie sie einfach abfragen, um festzustellen, ob sich etwas darin befindet.

Sie können jede Datenbank löschen, mit der Sie verbunden sind:

var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
    /* Drop the DB */
    mongoose.connection.db.dropDatabase();
});
Hölllam
quelle
1
Ich habe es versucht, mongoose.connection.db.dropDatabase()aber ich habe festgestellt, dass die Datenbank noch vorhanden ist. Vermisse ich etwas
Freilauf
Wenn Sie danach eine Verbindung herstellen, wird es neu erstellt, obwohl es leer ist. Gab es irgendwelche Sammlungen darin, nachdem Sie es fallen gelassen haben?
Hellslam
Verwenden Sie durchgehend dieselbe Verbindung oder erstellen Sie mehrere Verbindungen?
Hellslam
12
Ich fand, dass der dropDatabaseAufruf in den Rückruf von connect, as gesetzt werden sollte mongoose.connect('...', function() { ...dropDatabase()}).
Freilauf
1
dropDatabase scheint in einigen Fällen nicht zu funktionieren, aber der direkte Mongo-Befehl kann immer noch verwendet werden mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz
14

Wenn Sie die Lösung von @ hellslam wie folgt ändern, funktioniert sie

Ich verwende diese Technik, um die Datenbank nach meinen Integrationstests zu löschen

//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 hat es zumindest für mich getan, also habe ich beschlossen zu teilen =)

Silberkämpfer
quelle
ist es möglich, db damit fallen zu lassen? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
Chovy
2
Das war hilfreich, danke! Ihre Variablennamen sind jedoch etwas irreführend ... mongoose.connectkehren tatsächlich zurück mongoose. Anstatt conn = mongoose.connect(...)würde ich schreiben mongoose.connect(...)und dann conn = mongooose.connection.
Ein bezahlter Nerd
Ich denke nicht, dass dieser Code immer funktioniert, weil der connectasynchron ist. Wenn die Verbindung nicht sofort hergestellt wird, schlägt der Befehl dropDatabase () fehl. Aus diesem Grund wurde in den anderen oben genannten Lösungen empfohlen, den dropDatabaseBefehl in den Rückruf der connectAnweisung oder eines openEreignishandlers einzufügen.
Mark Stosberg
8

Versuchte die Antworten von @ hellslam und @ silverfighter. Ich fand eine Rennbedingung, die meine Tests zurückhielt. In meinem Fall führe ich Mokka-Tests durch und in der Vorher-Funktion des Tests möchte ich die gesamte Datenbank löschen. Folgendes funktioniert bei mir.

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

Sie können mehr unter https://github.com/Automattic/mongoose/issues/1469 lesen

zafrani
quelle
7

Eine aktualisierte Antwort für 4.6.0+, wenn Sie Versprechen bevorzugen ( siehe Dokumente ):

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

Ich habe diesen Code in meinem eigenen Code mit Mungo 4.13.6 getestet. Beachten Sie auch die Verwendung der useMongoClientOption ( siehe Dokumente ). Dokumente zeigen an:

Die Standardverbindungslogik von Mongoose ist ab 4.11.0 veraltet. Bitte aktivieren Sie die neue Verbindungslogik mit der Option useMongoClient. Testen Sie jedoch zuerst Ihre Verbindungen, wenn Sie eine vorhandene Codebasis aktualisieren!

Andre M.
quelle
5

Die Schwierigkeit, die ich mit den anderen Lösungen hatte, besteht darin, dass sie darauf angewiesen sind, Ihre Anwendung neu zu starten, wenn Sie möchten, dass die Indizes wieder funktionieren.

Für meine Anforderungen (dh in der Lage zu sein, einen Unit-Test der Atomwaffen aller Sammlungen durchzuführen und sie dann zusammen mit ihren Indizes neu zu erstellen), habe ich diese Lösung implementiert:

Dies hängt von den Bibliotheken underscore.js und async.js ab , um die Indizes parallel zusammenzustellen. Es könnte abgewickelt werden, wenn Sie gegen diese Bibliothek sind, aber ich überlasse dies dem Entwickler als Übungsgerät.

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
quelle
4

So leeren Sie eine bestimmte Sammlung in einer Datenbank:

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

Hinweis:

  1. Wählen Sie ein Modell aus, das sich auf ein bestimmtes Schema bezieht (Schema der Sammlung, die Sie löschen möchten).
  2. Durch diesen Vorgang wird der Sammlungsname nicht aus der Datenbank gelöscht.
  3. Dadurch werden alle Dokumente in einer Sammlung gelöscht.
dänisch
quelle
4

Dies funktioniert bei mir ab Mungo v4.7.0:

mongoose.connection.dropDatabase();
user3344977
quelle
4

Der beste Weg, Ihre Datenbank in Mongoose zu löschen, hängt davon ab, welche Version von Mongoose Sie verwenden. Wenn Sie eine Version von Mongoose verwenden, die 4.6.4 oder höher ist, funktioniert diese in dieser Version hinzugefügte Methode wahrscheinlich einwandfrei für Sie:

mongoose.connection.dropDatabase();

In älteren Versionen existierte diese Methode nicht. Stattdessen sollten Sie einen direkten MongoDB-Aufruf verwenden:

mongoose.connection.db.dropDatabase();

Wenn dies jedoch unmittelbar nach dem Erstellen der Datenbankverbindung ausgeführt wurde, kann es möglicherweise unbemerkt fehlschlagen. Dies hängt damit zusammen, dass die Verbindung tatsächlich asynchron ist und noch nicht eingerichtet wird, wenn der Befehl ausgeführt wird. Dies ist normalerweise kein Problem für andere Mongoose-Anrufe wie.find() , die sich in der Warteschlange befinden, bis die Verbindung geöffnet ist und dann ausgeführt wird.

Wenn Sie sich den Quellcode für die dropDatabase() hinzugefügte Verknüpfung , können Sie sehen, dass sie genau dieses Problem lösen soll. Es wird überprüft, ob die Verbindung offen und bereit ist. In diesem Fall wird der Befehl sofort ausgelöst. Wenn nicht, registriert es den Befehl, der ausgeführt werden soll, wenn die Datenbankverbindung geöffnet wurde.

Einige der oben genannten Vorschläge empfehlen immer Ihren Putting - dropDatabaseBefehl in dem openHandler. Dies funktioniert jedoch nur, wenn die Verbindung noch nicht geöffnet ist.

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

Hier ist eine einfache Version der obigen Logik, die mit früheren Mongoose-Versionen verwendet werden kann:

// 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
quelle
2

Mungo 4.6.0+:

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

Das Weiterleiten eines Rückrufs an die Verbindung funktioniert nicht mehr:

TypeError: Die Eigenschaft 'commandTakeWriteConcern' von null kann nicht gelesen werden

Rayjax
quelle
1
connectgibt ein Versprechen, so dass Sie hinzufügen können , .then((connection) => { ... });um die mongoose.connect. Siehe: 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.
quelle
0

Da die Methode remove in der Mungobibliothek nicht mehr verwendet wird, können wir die Funktion deleteMany verwenden, ohne dass Parameter übergeben werden.

Model.deleteMany();

Dadurch werden alle Inhalte dieses bestimmten Modells gelöscht und Ihre Sammlung ist leer.

SAYAM.S SANGHVI
quelle
0

So legen Sie alle Dokumente in einer Sammlung ab:

await mongoose.connection.db.dropDatabase();

Diese Antwort basiert auf der Datei mongoose index.d.ts:

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

So löschen Sie alle Dokumente in einer Sammlung:

myMongooseModel.collection.drop();

wie in den Tests gesehen

Sgnl
quelle