Як скинути базу даних з Мангустом?


97

Я готую сценарій створення бази даних у Node.js та Mongoose. Як я можу перевірити, чи існує база даних, і якщо так, видаліть (видаліть) її за допомогою Mongoose?

Я не міг знайти способу скинути це з мангустом.


Відповіді:


166

Не існує способу видалення колекції з мангуста, найкраще ви можете видалити вміст одного:

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

Але є спосіб отримати доступ до власного драйвера JavaScript mongodb, який можна використовувати для цього

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

Увага

Створіть резервну копію, перш ніж спробувати це у випадку, якщо щось піде не так!


2
коли я спробую другий варіант, я отримую "не можу прочитати властивість 'collectionName' undefined"
Yaron Naveh

1
Оскільки всі колекції в хеш mongoose.connection.collections, ви могли б просто перерахувати їх (збір в mongoose.connection.collections) {mongoose.connection.collections [колекція] .drop} ... подібний чому - л
drinchev

3
У вас є помилка друку - додаткова кома після функції (помилка) ... повинна бути: mongoose.connection.collections ['collectionName']. Drop (function (помилка) {console.log ('колекція випала') ;});
arxpoetica

3
Я єдиний, хто зрозумів цю відповідь, не стосується питання, як запустити базу даних. Його не просять кинути колекцію, її просять скинути базу даних ..
Джозеф Персі

3
"Немає способу скидання колекції з мангуста", насамперед ОП хоче видалити базу даних, а не збірку, по-друге, відповідь @hellslam нижче добре працює.
SCBuergel.eth

79

Mongoose створить базу даних, якщо такої ще не існує при з’єднанні, тож як тільки ви встановите з'єднання, ви можете просто запитати його, щоб побачити, чи є в ньому щось.

Ви можете скинути будь-яку базу даних, до якої ви підключені:

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

1
Я спробував, mongoose.connection.db.dropDatabase()але я виявив, що все ще є? Я щось сумую?
Freewind

Якщо ви після цього підключились до нього, він буде відтворений, хоч і порожній. Чи були в ній колекції після того, як ви її скинули?
hellslam

Ви використовуєте одне і те ж з'єднання протягом усього часу або створюєте кілька з'єднань?
hellslam

12
Я виявив, що dropDatabaseвиклик повинен бути розміщений у зворотному дзвінку connect, як mongoose.connect('...', function() { ...dropDatabase()}).
Freewind

1
Схоже, в деяких випадках dropDatabase не працює, але все ж можна використовувати пряму команду mongo mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz

14

Якщо ви модифікуєте подібне рішення @ hellslam, воно працюватиме

Я використовую цю техніку, щоб скинути Базу даних після моїх інтеграційних тестів

//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 принаймні це зробив для мене, тому я вирішив поділитися =)


чи можна скинути db за допомогою цього? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy

2
Це було корисно, дякую! Однак імена вашої змінної трохи вводять в оману ... mongoose.connectнасправді повертається mongoose. Замість того conn = mongoose.connect(...), щоб писати mongoose.connect(...)і тоді conn = mongooose.connection.
платний ботанік

Я не думаю, що цей код завжди працюватиме, оскільки connectасинхронний. Отже, якщо з'єднання не відбудеться відразу, команда dropDatabase () вийде з ладу. Ось чому в інших вище рішеннях рекомендується додавати dropDatabaseкоманду до зворотного дзвінка до connectоператора чи openобробника подій.
Марк Стосберг

8

Спробував відповіді @ hellslam та @ silverfighter. Я виявив стан гонки, який стримував мої тести. У моєму випадку я виконую мок-тести, і в функції тесту до того, як я хочу стерти всю БД. Ось що для мене працює.

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

Ви можете прочитати більше https://github.com/Automattic/mongoose/isissue/1469


7

Оновлена ​​відповідь, для 4.6.0 і новіших версій, якщо ви віддаєте перевагу обіцянкам ( див. Документи ):

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

Я перевірив цей код у власному коді, використовуючи мангуст 4.13.6. Також зверніть увагу на використання useMongoClientопції ( див. Документи ). Документи вказують:

Логіка підключення за замовчуванням Mongoose застаріла з 4.11.0. Будь ласка, увімкніть нову логіку підключення за допомогою параметра useMongoClient, але переконайтесь, що ви перевірили свої з'єднання спочатку, якщо оновлюєте існуючу базу коду!


5

Складність у мене з іншими рішеннями полягає в тому, що вони покладаються на перезапуск програми, якщо ви хочете, щоб індекси знову працювали.

Для моїх потреб (тобто можливість запустити блок тестування ядер усіх колекцій, а потім відтворити їх разом з їх індексами) я закінчив реалізувати це рішення:

Це покладається на бібліотеки underscore.js та async.js для збирання індексів у parellel, це може бути розкручено, якщо ви проти цієї бібліотеки, але я залишаю це як тренер для розробника.

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

Щоб очистити певну колекцію в базі даних:

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

Примітка:

  1. Виберіть модель, що стосується певної схеми (схему колекції, яку ви хочете видалити).
  2. Ця операція не видалить ім'я колекції з бази даних.
  3. Це видаляє всі документи в колекції.

4

Це працює для мене від Мангуста v4.7.0:

mongoose.connection.dropDatabase();

4

Найкращий спосіб скинути свою базу даних у Мангусту залежить від того, яку версію Mongoose ви використовуєте. Якщо ви користуєтеся версією Mongoose, що має 4.6.4 або новішої версії, то цей метод, доданий у цьому випуску, швидше за все, спрацює нормально:

mongoose.connection.dropDatabase();

У старих випусках цього методу не існувало. Натомість ви повинні використовувати прямий дзвінок MongoDB:

mongoose.connection.db.dropDatabase();

Однак якщо це було запущено відразу після створення з'єднання з базою даних, можливо, воно могло б вийти з ладу. Це пов'язано з тим, що з'єднання насправді має бути асинхронним і ще не встановлюється, коли команда відбувається. Зазвичай це не є проблемою для інших дзвінків Mongoose, таких як .find()черга, поки з'єднання не буде відкритим, а потім запущено.

Якщо ви подивитеся на вихідний код dropDatabase()ярлика, який був доданий, ви можете побачити, що він був розроблений для вирішення цієї точної проблеми. Він перевіряє, чи є з'єднання відкритим і готовим. Якщо так, то команда виконується негайно. Якщо ні, він реєструє команду, яку потрібно запустити, коли з'єднання з базою даних відкрилося.

Деякі з наведених вище пропозицій рекомендують завжди вводити свою dropDatabaseкоманду в openобробник. Але це працює лише в тому випадку, коли з'єднання ще не відкрите.

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

Ось проста версія вищеописаної логіки, яку можна використовувати з попередніми версіями 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

Мангуст 4.6.0+:

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

Передача зворотного дзвінка для підключення більше не працюватиме:

TypeError: Неможливо прочитати властивість 'commandTakeWriteConcern' з null


1
connectповертає обіцянку, тому ви можете додати .then((connection) => { ... });до mongoose.connect. Дивіться: mongoosejs.com/docs/connections.html
Андре М

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

0

Оскільки метод видалення амортизується в бібліотеці мангустів, ми можемо використовувати функцію deleteMany без переданих параметрів.

Model.deleteMany();

Це видалить увесь вміст цієї конкретної Моделі, і ваша колекція буде порожньою.


0

Щоб скинути всі документи в колекцію:

await mongoose.connection.db.dropDatabase();

Ця відповідь заснована на файлі мангуста index.d.ts:

dropDatabase(): Promise<any>;

-2

Для видалення всіх документів у колекцію:

myMongooseModel.collection.drop();

як видно з тестів

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.