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


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.