Как удалить базу данных с помощью Mongoose?

97

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

Я не мог найти способ сбросить это с помощью Mongoose.

Ярон Навех
источник
Дубликат: stackoverflow.com/questions/11453617/…
Удай Хиварале,

Ответы:

166

Не существует метода удаления коллекции из мангуста, лучшее, что вы можете сделать, - это удалить содержимое одной из них:

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

Но есть способ получить доступ к собственному javascript-драйверу mongodb, который можно использовать для этого

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

Предупреждение

Сделайте резервную копию, прежде чем пытаться это сделать, на случай, если что-то пойдет не так!

Дринчев
источник
2
когда я пробую второй вариант, я получаю «не могу прочитать свойство 'collectionName' of undefined»
Ярон Навех
1
Поскольку все коллекции находятся в хэше mongoose.connection.collections, вы можете просто перечислить их для (коллекции в mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ... что-то подобное
drinchev
3
У вас есть опечатка - дополнительная запятая после функции (err) ... должна быть: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
arxpoetica
3
Я единственный, кто понял, что этот ответ не касается вопроса о том, как удалить базу данных. Это не просьба сбросить коллекцию, а просьбу сбросить базу данных ..
Джозеф Перси
3
«Нет метода для удаления коллекции из мангуста», во-первых, OP хочет удалить базу данных, а не сборку, во-вторых, ответ @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вызов следует поместить в обратный вызов connectas 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 = 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/issues/1469

зафрани
источник
7

Обновленный ответ для 4.6.0+, если вы предпочитаете обещания ( см. Документы ):

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

Я тестировал этот код в своем собственном коде, используя mongoose 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

Это работает для меня с Mongoose v4.7.0:

mongoose.connection.dropDatabase();
user3344977
источник
4

Лучший способ удалить базу данных в Mongoose зависит от того, какую версию 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

Rayjax
источник
1
connectвозвращает обещание, поэтому вы можете добавить его .then((connection) => { ... });к mongoose.connect. См .: 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
источник
0

Поскольку в библиотеке mongoose метод remove не используется, мы можем использовать функцию deleteMany без переданных параметров.

Model.deleteMany();

Это приведет к удалению всего содержимого этой конкретной модели, и ваша коллекция будет пустой.

САЯМ.САНГХВИ
источник
0

Чтобы удалить все документы в коллекции:

await mongoose.connection.db.dropDatabase();

Этот ответ основан на файле mongoose index.d.ts:

dropDatabase(): Promise<any>;
mrhid3f
источник
-2

Чтобы удалить все документы в коллекции:

myMongooseModel.collection.drop();

как видно в тестах

Sgnl
источник