【发布时间】:2012-04-22 07:30:13
【问题描述】:
我正在用 Node.js 和 Mongoose 准备一个数据库创建脚本。 如何检查数据库是否已经存在,如果存在,使用 Mongoose 删除(删除)它?
我找不到用 Mongoose 删除它的方法。
【问题讨论】:
我正在用 Node.js 和 Mongoose 准备一个数据库创建脚本。 如何检查数据库是否已经存在,如果存在,使用 Mongoose 删除(删除)它?
我找不到用 Mongoose 删除它的方法。
【问题讨论】:
没有办法从猫鼬中删除一个集合,你能做的最好的就是删除一个集合的内容:
Model.remove({}, function(err) {
console.log('collection removed')
});
但是有一种方法可以访问mongodb原生的javascript驱动,可以用这个
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的回调中,如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();
至少它对我有用,所以我决定分享 =)
【讨论】:
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 的答案。我发现一个比赛条件阻碍了我的测试。就我而言,我正在运行 mocha 测试,并且在测试的前功能中我想擦除整个数据库。这对我有用。
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
con.connection.db.dropDatabase(function(err, result){
done();
});
});
【讨论】:
4.6.0+ 的更新答案,如果您偏好 Promise (see docs):
mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
connection.db.dropDatabase();
// alternatively:
// mongoose.connection.db.dropDatabase();
});
我使用 mongoose 4.13.6 在自己的代码中测试了这段代码。另外,请注意useMongoClient 选项(see docs)的使用。文档表明:
Mongoose 的默认连接逻辑自 4.11.0 起已弃用。请使用 useMongoClient 选项选择新的连接逻辑,但如果您要升级现有代码库,请确保首先测试您的连接!
【讨论】:
我在使用其他解决方案时遇到的困难是,如果您想让索引再次工作,它们依赖于重新启动您的应用程序。
出于我的需要(即能够对所有集合进行单元测试,然后重新创建它们及其索引),我最终实现了这个解决方案:
这依赖于 underscore.js 和 async.js 库以并行方式组装索引,如果您反对该库,它可能会被取消,但我将其作为开发人员的练习器。
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')
})
})
})
【讨论】:
这对我来说适用于 Mongoose v4.7.0:
mongoose.connection.dropDatabase();
【讨论】:
清空数据库中的特定集合:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
注意:
【讨论】:
在 Mongoose 中删除数据库的最佳方法取决于您使用的 Mongoose 版本。如果您使用的是 4.6.4 或更高版本的 Mongoose,那么在该版本中添加的这个方法很可能适合您:
mongoose.connection.dropDatabase();
在旧版本中,此方法不存在。相反,您将使用直接 MongoDB 调用:
mongoose.connection.db.dropDatabase();
但是,如果它是在数据库连接创建之后运行的,它可能会静默失败。这与连接实际上是异步的并且在命令发生时尚未建立有关。对于像 .find() 这样的其他 Mongoose 调用,这通常不是问题,它们会排队等待连接打开然后运行。
如果您查看添加的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:无法读取 null 的属性“commandsTakeWriteConcern”
【讨论】:
connect 返回一个承诺,因此您可以将.then((connection) => { ... }); 添加到mongoose.connect。见:mongoosejs.com/docs/connections.html
2020 年更新
创建一个名为 drop.js 的新文件,即 并放入里面
require('dotenv').config()
const url = process.env.ATLAS_URI;
mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: false
});
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
})
mongoose.connection.dropDatabase().then(
async() => {
try {
mongoose.connection.close()
}
catch (err) {
console.log(err)
}
}
);
在你的 package.json 中
in your package.json
"scripts": {
"drop": "node models/drop.js",
}
在您的控制台上运行它并
【讨论】:
beforeEach((done) => {
mongoose.connection.dropCollection('products',(error ,result) => {
if (error) {
console.log('Products Collection is not dropped')
} else {
console.log(result)
}
done()
})
})
【讨论】:
要删除集合中的所有文档:
await mongoose.connection.db.dropDatabase();
此答案基于 mongoose index.d.ts 文件:
dropDatabase(): Promise<any>;
【讨论】:
mongoose.connect(`mongodb://localhost/${dbname}`, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: true,
useUnifiedTopology: true
})
.then((connection) => {
mongoose.connection.db.dropDatabase();
});
要删除一个完整的数据库,只需传递名称... 这个在 4.4 版上运行良好
【讨论】:
由于 mongoose 库中的 remove 方法已被弃用,我们可以使用不传递参数的 deleteMany 函数。
Model.deleteMany();
这将删除此特定模型的所有内容,您的收藏将是空的。
【讨论】:
【讨论】: