Comment supprimer une base de données avec Mongoose?

97

Je prépare un script de création de base de données dans Node.js et Mongoose. Comment puis-je vérifier si la base de données existe déjà et si oui, la supprimer (la supprimer) à l'aide de Mongoose?

Je n'ai pas pu trouver un moyen de le laisser tomber avec Mongoose.

Yaron Naveh
la source
Dupliquer: stackoverflow.com/questions/11453617/…
Uday Hiwarale

Réponses:

166

Il n'y a pas de méthode pour supprimer une collection de mangouste, le mieux que vous puissiez faire est d'en supprimer le contenu:

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

Mais il existe un moyen d'accéder au pilote javascript natif de mongodb, qui peut être utilisé pour cela

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

avertissement

Faites une sauvegarde avant d'essayer cela au cas où quelque chose ne va pas!

Drinchev
la source
2
quand j'essaye la deuxième option j'obtiens "ne peut pas lire la propriété 'collectionName' d'undefined"
Yaron Naveh
1
Puisque toutes les collections sont dans le hash mongoose.connection.collections, vous pouvez simplement les lister pour (collection dans mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ... tout de même similaire
drinchev
3
Vous avez une faute de frappe - une virgule supplémentaire après la fonction (err) ... devrait être: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection supprimée') ;});
arxpoetica
3
Suis-je le seul à avoir réalisé que cette réponse n'aborde pas la question de savoir comment supprimer une base de données. Il ne demande pas de supprimer une collection, il demande de supprimer une base de données.
Joseph Persie
3
"Il n'y a pas de méthode pour supprimer une collection de mangouste", tout d'abord l'OP veut supprimer une base de données, pas une collection, ensuite la réponse de @hellslam ci-dessous fonctionne bien.
SCBuergel.eth
79

Mongoose créera une base de données s'il n'en existe pas déjà une lors de la connexion, donc une fois la connexion établie, vous pouvez simplement l'interroger pour voir s'il contient quelque chose.

Vous pouvez supprimer toute base de données à laquelle vous êtes connecté:

var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
    /* Drop the DB */
    mongoose.connection.db.dropDatabase();
});
Hellslam
la source
1
J'ai essayé mongoose.connection.db.dropDatabase()mais j'ai trouvé que la base de données est toujours là? Est-ce que je rate quelque chose?
Freewind
Si vous vous y connectez par la suite, il sera recréé, bien que vide. Y avait-il des collections après l'avoir déposé?
hellslam
Utilisez-vous la même connexion partout ou créez-vous plusieurs connexions?
hellslam
12
J'ai trouvé que l' dropDatabaseinvocation devait être placée dans le rappel de connect, comme mongoose.connect('...', function() { ...dropDatabase()}).
Freewind
1
dropDatabase semble ne pas fonctionner dans certains cas, mais la commande directe mongo peut toujours être utilisée mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz
14

Si vous modifiez la solution de @ hellslam de cette manière, cela fonctionnera

J'utilise cette technique pour supprimer la base de données après mes tests d'intégration

//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 au moins ça l'a fait pour moi, alors j'ai décidé de partager =)

silverfighter
la source
est-il possible de supprimer db avec ça? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy
2
Cela a été utile, merci! Cependant, vos noms de variables sont un peu trompeurs ... mongoose.connectretourne en fait mongoose. Au lieu d' conn = mongoose.connect(...)écrire mongoose.connect(...)et puis conn = mongooose.connection.
un nerd payé
Je ne pense pas que ce code fonctionnera toujours car il connectest asynchrone. Donc, si la connexion ne se produit pas immédiatement, la commande dropDatabase () échouera. C'est pourquoi les autres solutions ci-dessus recommandaient de placer la dropDatabasecommande dans le rappel de l' connectinstruction ou d'un opengestionnaire d'événements.
Mark Stosberg
8

J'ai essayé les réponses de @ hellslam et @ silverfighter. J'ai trouvé une condition de course retenant mes tests. Dans mon cas, j'exécute des tests moka et dans la fonction avant du test, je veux effacer toute la base de données. Voici ce qui fonctionne pour moi.

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

Vous pouvez en savoir plus https://github.com/Automattic/mongoose/issues/1469

zafrani
la source
7

Une réponse mise à jour, pour 4.6.0+, si vous avez une préférence pour les promesses ( voir la documentation ):

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

J'ai testé ce code dans mon propre code, en utilisant mongoose 4.13.6. Notez également l'utilisation de l' useMongoClientoption ( voir la documentation ). Les documents indiquent:

La logique de connexion par défaut de Mongoose est obsolète à partir de la version 4.11.0. Veuillez activer la nouvelle logique de connexion à l'aide de l'option useMongoClient, mais assurez-vous de tester d'abord vos connexions si vous mettez à niveau une base de code existante!

André M
la source
5

La difficulté que j'ai rencontrée avec les autres solutions est qu'elles reposent sur le redémarrage de votre application si vous souhaitez que les index fonctionnent à nouveau.

Pour mes besoins (c'est-à-dire pouvoir exécuter un test unitaire sur toutes les collections d'armes nucléaires, puis les recréer avec leurs index), j'ai fini par implémenter cette solution:

Cela repose sur les bibliothèques underscore.js et async.js pour assembler les index en parallèle, cela pourrait être déroulé si vous êtes contre cette bibliothèque, mais je laisse cela comme un exercice pour le développeur.

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
la source
4

Pour vider une collection particulière dans une base de données:

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

Remarque:

  1. Choisissez un modèle faisant référence à un schéma particulier (schéma de collection que vous souhaitez supprimer).
  2. Cette opération ne supprimera pas le nom de la collection de la base de données.
  3. Cela supprime tous les documents d'une collection.
danois
la source
4

Cela fonctionne pour moi à partir de Mongoose v4.7.0:

mongoose.connection.dropDatabase();
user3344977
la source
4

La meilleure façon de déposer votre base de données dans Mongoose dépend de la version de Mongoose que vous utilisez. Si vous utilisez une version de Mongoose que 4.6.4 ou plus récente, alors cette méthode ajoutée dans cette version fonctionnera probablement bien pour vous:

mongoose.connection.dropDatabase();

Dans les versions plus anciennes, cette méthode n'existait pas. Au lieu de cela, vous deviez utiliser un appel MongoDB direct:

mongoose.connection.db.dropDatabase();

Cependant, si cela était exécuté juste après la création de la connexion à la base de données, il pourrait éventuellement échouer silencieusement. Ceci est lié au fait que la connexion est réellement asynchrone et n'est pas encore configurée lorsque la commande se produit. Ce n'est normalement pas un problème pour les autres appels Mongoose comme .find(), quelle file d'attente jusqu'à ce que la connexion soit ouverte, puis exécutée.

Si vous regardez le code source du dropDatabase()raccourci qui a été ajouté, vous pouvez voir qu'il a été conçu pour résoudre exactement ce problème. Il vérifie si la connexion est ouverte et prête. Si tel est le cas, il déclenche la commande immédiatement. Sinon, il enregistre la commande à exécuter lorsque la connexion à la base de données est ouverte.

Certaines des suggestions ci-dessus recommandent de toujours placer votre dropDatabasecommande dans le opengestionnaire. Mais cela ne fonctionne que dans le cas où la connexion n'est pas encore ouverte.

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

Voici une version simple de la logique ci-dessus qui peut être utilisée avec les versions antérieures 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
la source
2

Mongoose 4.6.0+:

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

Passer un rappel pour se connecter ne fonctionnera plus:

TypeError: impossible de lire la propriété 'commandsTakeWriteConcern' de null

Rayjax
la source
1
connectrenvoie une promesse, vous pouvez donc ajouter .then((connection) => { ... });au mongoose.connect. Voir: 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
la source
0

Puisque la méthode remove est dépréciée dans la bibliothèque mangouste, nous pouvons utiliser la fonction deleteMany sans aucun paramètre passé.

Model.deleteMany();

Cela supprimera tout le contenu de ce modèle particulier et votre collection sera vide.

SAYAM.S SANGHVI
la source
0

Pour déposer tous les documents d'une collection:

await mongoose.connection.db.dropDatabase();

Cette réponse est basée sur le fichier mongoose index.d.ts:

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

Pour déposer tous les documents d'une collection:

myMongooseModel.collection.drop();

comme vu dans les tests

Sgnl
la source