Tôi đang chuẩn bị một tập lệnh tạo cơ sở dữ liệu trong Node.js và Mongoose. Làm cách nào để kiểm tra xem cơ sở dữ liệu đã tồn tại chưa và nếu có, hãy thả (xóa) nó bằng Mongoose?
Tôi không thể tìm ra cách để bỏ nó với Mongoose.
Tôi đang chuẩn bị một tập lệnh tạo cơ sở dữ liệu trong Node.js và Mongoose. Làm cách nào để kiểm tra xem cơ sở dữ liệu đã tồn tại chưa và nếu có, hãy thả (xóa) nó bằng Mongoose?
Tôi không thể tìm ra cách để bỏ nó với Mongoose.
Câu trả lời:
Không có phương pháp nào để loại bỏ một bộ sưu tập khỏi mongoose, cách tốt nhất bạn có thể làm là xóa nội dung của một bộ sưu tập:
Model.remove({}, function(err) {
console.log('collection removed')
});
Nhưng có một cách để truy cập trình điều khiển javascript gốc mongodb, có thể được sử dụng cho việc này
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
Hãy sao lưu trước khi thử điều này trong trường hợp có bất kỳ sự cố nào xảy ra!
Mongoose sẽ tạo một cơ sở dữ liệu nếu một cơ sở dữ liệu chưa tồn tại trên kết nối, vì vậy khi bạn thực hiện kết nối, bạn chỉ có thể truy vấn nó để xem có bất kỳ thứ gì trong đó hay không.
Bạn có thể loại bỏ bất kỳ cơ sở dữ liệu nào mà bạn được kết nối:
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()
nhưng tôi thấy db vẫn còn ở đó? Tôi có bỏ lỡ điều gì không?
dropDatabase
lời gọi nên được đặt trong lệnh gọi lại của connect
, như mongoose.connect('...', function() { ...dropDatabase()})
.
mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
Nếu bạn sửa đổi giải pháp của @ hellslam như thế này thì nó sẽ hoạt động
Tôi sử dụng kỹ thuật này để loại bỏ Cơ sở dữ liệu sau khi kiểm tra tích hợp của tôi
//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 ít nhất nó đã làm cho tôi, vì vậy tôi quyết định chia sẻ =)
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
thực sự trả về mongoose
. Thay vì conn = mongoose.connect(...)
tôi sẽ viết mongoose.connect(...)
và sau đó conn = mongooose.connection
.
connect
không đồng bộ. Vì vậy, nếu kết nối không xảy ra ngay lập tức, lệnh dropDatabase () sẽ không thành công. Đó là lý do tại sao các giải pháp khác ở trên khuyến nghị đặt dropDatabase
lệnh trong lệnh gọi lại connect
câu lệnh hoặc open
trình xử lý sự kiện.
Đã thử câu trả lời của @ hellslam và @ silverfighter. Tôi tìm thấy một tình trạng cuộc đua đang giữ lại các bài kiểm tra của tôi. Trong trường hợp của tôi, tôi đang chạy các bài kiểm tra mocha và trong chức năng trước của bài kiểm tra, tôi muốn xóa toàn bộ DB. Đây là những gì phù hợp với tôi.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
con.connection.db.dropDatabase(function(err, result){
done();
});
});
Bạn có thể đọc thêm https://github.com/Automattic/mongoose/issues/1469
Một câu trả lời được cập nhật, cho 4.6.0+, nếu bạn thích những lời hứa ( xem tài liệu ):
mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
connection.db.dropDatabase();
// alternatively:
// mongoose.connection.db.dropDatabase();
});
Tôi đã thử nghiệm mã này trong mã của riêng mình, sử dụng mongoose 4.13.6. Ngoài ra, hãy lưu ý việc sử dụng useMongoClient
tùy chọn ( xem tài liệu ). Tài liệu cho biết:
Logic kết nối mặc định của Mongoose không được chấp nhận kể từ 4.11.0. Vui lòng chọn tham gia vào logic kết nối mới bằng cách sử dụng tùy chọn useMongoClient, nhưng hãy đảm bảo rằng bạn kiểm tra các kết nối của mình trước nếu bạn đang nâng cấp cơ sở mã hiện có!
Khó khăn mà tôi gặp phải với các giải pháp khác là chúng dựa vào việc khởi động lại ứng dụng của bạn nếu bạn muốn các chỉ mục hoạt động trở lại.
Đối với nhu cầu của tôi (nghĩa là có thể chạy một đơn vị kiểm tra hạt nhân tất cả các bộ sưu tập, sau đó tạo lại chúng cùng với các chỉ mục của chúng), tôi đã thực hiện giải pháp này:
Điều này dựa vào các thư viện underscore.js và async.js để tập hợp các chỉ mục theo song song, nó có thể không bị ràng buộc nếu bạn chống lại thư viện đó nhưng tôi để đó như một bài tập cho nhà phát triển.
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')
})
})
})
Để làm trống một bộ sưu tập cụ thể trong cơ sở dữ liệu:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
Ghi chú:
Điều này phù hợp với tôi kể từ Mongoose v4.7.0
:
mongoose.connection.dropDatabase();
Cách tốt nhất để thả cơ sở dữ liệu của bạn trong Mongoose tùy thuộc vào phiên bản Mongoose bạn đang sử dụng. Nếu bạn đang sử dụng phiên bản Mongoose 4.6.4 hoặc mới hơn, thì phương pháp này được thêm vào bản phát hành đó có thể sẽ hoạt động tốt cho bạn:
mongoose.connection.dropDatabase();
Trong các phiên bản cũ hơn, phương pháp này không tồn tại. Thay vào đó, bạn phải sử dụng cuộc gọi MongoDB trực tiếp:
mongoose.connection.db.dropDatabase();
Tuy nhiên, nếu điều này được chạy ngay sau khi kết nối cơ sở dữ liệu được tạo, nó có thể bị lỗi một cách âm thầm. Điều này liên quan đến kết nối thực sự không đồng bộ và chưa được thiết lập khi lệnh xảy ra. Đây thường không phải là vấn đề đối với các cuộc gọi Mongoose khác như .find()
xếp hàng đợi cho đến khi kết nối được mở và sau đó chạy.
Nếu bạn nhìn vào mã nguồn của dropDatabase()
phím tắt đã được thêm vào, bạn có thể thấy nó được thiết kế để giải quyết vấn đề chính xác này. Nó kiểm tra xem kết nối đã mở và sẵn sàng chưa. Nếu vậy, nó sẽ kích hoạt lệnh ngay lập tức. Nếu không, nó sẽ đăng ký lệnh để chạy khi kết nối cơ sở dữ liệu đã mở.
Một số gợi ý ở trên khuyên bạn nên luôn đặt dropDatabase
lệnh của bạn trong open
trình xử lý. Nhưng điều đó chỉ hoạt động trong trường hợp khi kết nối chưa được mở.
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;
};
Đây là một phiên bản đơn giản của logic trên có thể được sử dụng với các phiên bản Mongoose trước đó:
// 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);
}
}
Mongoose 4.6.0+:
mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
mongoose.connection.db.dropDatabase();
});
Chuyển cuộc gọi lại để kết nối sẽ không hoạt động nữa:
TypeError: Không thể đọc thuộc tính 'commandTakeWriteConcern' của null
connect
trả về một lời hứa, vì vậy bạn có thể thêm .then((connection) => { ... });
vào mongoose.connect
. Xem: mongoosejs.com/docs/connections.html
beforeEach((done) => {
mongoose.connection.dropCollection('products',(error ,result) => {
if (error) {
console.log('Products Collection is not dropped')
} else {
console.log(result)
}
done()
})
})
Vì phương thức remove được tính trong thư viện mongoose, chúng ta có thể sử dụng hàm deleteMany mà không có tham số nào được truyền vào.
Model.deleteMany();
Thao tác này sẽ xóa tất cả nội dung của Mô hình cụ thể này và bộ sưu tập của bạn sẽ trống.
Để bỏ tất cả tài liệu trong một bộ sưu tập:
myMongooseModel.collection.drop();
như đã thấy trong các bài kiểm tra