Я готовлю сценарий создания базы данных на Node.js и Mongoose. Как я могу проверить, существует ли уже база данных, и если да, удалить (удалить) ее с помощью Mongoose?
Я не мог найти способ сбросить это с помощью Mongoose.
Я готовлю сценарий создания базы данных на Node.js и Mongoose. Как я могу проверить, существует ли уже база данных, и если да, удалить (удалить) ее с помощью Mongoose?
Я не мог найти способ сбросить это с помощью Mongoose.
Ответы:
Не существует метода удаления коллекции из мангуста, лучшее, что вы можете сделать, - это удалить содержимое одной из них:
Model.remove({}, function(err) {
console.log('collection removed')
});
Но есть способ получить доступ к собственному javascript-драйверу mongodb, который можно использовать для этого
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
Сделайте резервную копию, прежде чем пытаться это сделать, на случай, если что-то пойдет не так!
Mongoose создаст базу данных, если она еще не существует при подключении, поэтому после установления соединения вы можете просто запросить ее, чтобы узнать, есть ли в ней что-нибудь.
Вы можете удалить любую базу данных, к которой вы подключены:
var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
/* Drop the DB */
mongoose.connection.db.dropDatabase();
});
mongoose.connection.db.dropDatabase()
но обнаружил, что БД все еще там? Я что-то упускаю?
dropDatabase
вызов следует поместить в обратный вызов connect
as mongoose.connect('...', function() { ...dropDatabase()})
.
mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
Если вы измените решение @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);
mongoose.connect
самом деле возвращает mongoose
. Вместо того, conn = mongoose.connect(...)
чтобы писать mongoose.connect(...)
и потом conn = mongooose.connection
.
connect
он асинхронный. Поэтому, если соединение не произойдет сразу, команда dropDatabase () завершится ошибкой. Вот почему другие решения выше рекомендовали помещать dropDatabase
команду в обратный вызов для connect
оператора или open
обработчика событий.
Пробовал ответы @ 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
Обновленный ответ для 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, но убедитесь, что вы сначала протестируете свои подключения, если вы обновляете существующую кодовую базу!
Трудность, с которой я столкнулся с другими решениями, заключается в том, что они полагаются на перезапуск вашего приложения, если вы хотите, чтобы индексы снова заработали.
Для моих нужд (то есть для возможности запустить модульное тестирование всех коллекций ядерных бомб, а затем воссоздать их вместе с их индексами) я реализовал это решение:
Это полагается на библиотеки 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')
})
})
})
Чтобы очистить конкретную коллекцию в базе данных:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
Примечание:
Это работает для меня с Mongoose v4.7.0
:
mongoose.connection.dropDatabase();
Лучший способ удалить базу данных в 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);
}
}
Мангуст 4.6.0+:
mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
mongoose.connection.db.dropDatabase();
});
Передача обратного вызова для подключения больше не будет работать:
TypeError: невозможно прочитать свойство commandTakeWriteConcern со значением null
connect
возвращает обещание, поэтому вы можете добавить его .then((connection) => { ... });
к mongoose.connect
. См .: mongoosejs.com/docs/connections.html
Поскольку в библиотеке mongoose метод remove не используется, мы можем использовать функцию deleteMany без переданных параметров.
Model.deleteMany();
Это приведет к удалению всего содержимого этой конкретной модели, и ваша коллекция будет пустой.