web-dev-qa-db-fra.com

Comment déposer une base de données avec Mongoose?

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, le cas échéant, supprimez-la à l'aide de Mongoose?

Je ne pouvais pas trouver un moyen de le laisser tomber avec Mongoose.

87
Yaron Naveh

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

Attention

Faites une sauvegarde avant d'essayer ceci au cas où quelque chose se passe mal!

152
drinchev

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

Vous pouvez supprimer n'importe quelle 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();
});
73
hellslam

Si vous modifiez la solution de @ hellslam comme ceci, alors 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 =)

14
silverfighter

Essayé réponses de @ hellslam et @ silverfighter. J'ai trouvé une condition de concurrence retardant mes tests. Dans mon cas, je lance des tests mocha 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 lire plus https://github.com/Automattic/mongoose/issues/1469

8
zafrani

Le problème que j'ai eu avec les autres solutions est qu'elles reposent sur le redémarrage de votre application si vous voulez que les index fonctionnent à nouveau.

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

Ceci repose sur les bibliothèques underscore.js et async.js pour assembler les index en parallèle, cela pourrait être résolu si vous êtes contre cette bibliothèque mais je laisse cela comme un exerciseur 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')
    })
  })
})
5
Eric Caron

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.__ 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.
4
Danish

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

mongoose.connection.dropDatabase();
4
user3344977

La meilleure façon de supprimer votre base de données dans Mongoose dépend de la version de Mongoose que vous utilisez. Si vous utilisez une version de Mongoose version 4.6.4 ou ultérieure, cette méthode ajoutée dans cette version fonctionnera probablement très bien pour vous:

mongoose.connection.dropDatabase();

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

mongoose.connection.db.dropDatabase();

Toutefois, si cette opération était exécutée juste après la création de la connexion à la base de données, elle pourrait éventuellement échouer en mode silencieux. Cela est lié au fait que la connexion est réellement asynchrone et n’a pas encore été configurée lorsque la commande est exécutée. Ce n'est normalement pas un problème pour les autres appels Mongoose comme .find(), qui attendent jusqu'à ce que la connexion soit ouverte et ensuite exécutée.

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

Certaines des suggestions ci-dessus recommandent always de placer votre commande dropDatabase dans le gestionnaire open. 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);
    }
}  
3
Mark Stosberg

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

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 mangouste 4.13.6. Notez également l’utilisation de l’option useMongoClient ( voir docs ). Les documents indiquent: 

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

3
Andre M

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é 'ordersTakeWriteConcern' of null

1
Rayjax
beforeEach((done) => {
      mongoose.connection.dropCollection('products',(error ,result) => {
      if (error) {
        console.log('Products Collection is not dropped')
      } else {
        console.log(result)
      }
    done()
    })
  })
0
Revt A