Node.js ve Mongoose'da bir veritabanı oluşturma komut dosyası hazırlıyorum. Veritabanının zaten var olup olmadığını nasıl kontrol edebilirim ve eğer öyleyse, Mongoose kullanarak onu bırak (sil)?
Mongoose ile bırakmanın bir yolunu bulamadım.
Node.js ve Mongoose'da bir veritabanı oluşturma komut dosyası hazırlıyorum. Veritabanının zaten var olup olmadığını nasıl kontrol edebilirim ve eğer öyleyse, Mongoose kullanarak onu bırak (sil)?
Mongoose ile bırakmanın bir yolunu bulamadım.
Yanıtlar:
Firavun faresinden bir koleksiyon düşürmenin bir yöntemi yoktur, yapabileceğiniz en iyi şey birinin içeriğini kaldırmaktır:
Model.remove({}, function(err) {
console.log('collection removed')
});
Ancak bunun için kullanılabilecek mongodb yerel javascript sürücüsüne erişmenin bir yolu vardır.
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
Bir şeyler ters giderse diye bunu denemeden önce bir yedek alın!
Mongoose, bağlantıda zaten mevcut değilse bir veritabanı oluşturacaktır, bu nedenle bağlantıyı kurduğunuzda, içinde bir şey olup olmadığını görmek için onu sorgulayabilirsiniz.
Bağlı olduğunuz herhangi bir veritabanını bırakabilirsiniz:
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()
ama db'nin hala orada olduğunu buldum? Bir şey mi özledim?
dropDatabase
Çağrının connect
, olarak geri aramasına yerleştirilmesi gerektiğini buldum mongoose.connect('...', function() { ...dropDatabase()})
.
mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
@ Hellslam'ın çözümünü bu şekilde değiştirirseniz işe yarayacaktır.
Entegrasyon testlerimden sonra Veritabanını bırakmak için bu tekniği kullanıyorum
//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 en azından benim için yaptı, bu yüzden paylaşmaya karar verdim =)
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
aslında geri döner mongoose
. Bunun yerine conn = mongoose.connect(...)
yazacağım mongoose.connect(...)
ve sonra conn = mongooose.connection
.
connect
Asenkron olduğu için bu kodun her zaman çalışacağını sanmıyorum . Dolayısıyla, bağlantı hemen gerçekleşmezse, dropDatabase () komutu başarısız olur. Bu nedenle yukarıdaki diğer çözümler, dropDatabase
komutun connect
ifadeye veya bir open
olay işleyicisine yapılan geri aramaya koyulmasını önermiştir.
@ Hellslam ve @ silverfighter'ın cevaplarını denedi. Testlerimi geciktiren bir yarış durumu buldum. Benim durumumda mocha testleri yapıyorum ve testin önceki işlevinde tüm DB'yi silmek istiyorum. İşte benim için işe yarayan şey.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
con.connection.db.dropDatabase(function(err, result){
done();
});
});
Daha fazla https://github.com/Automattic/mongoose/issues/1469 okuyabilirsiniz
Sözler için bir tercihiniz varsa, 4.6.0+ için güncellenmiş bir cevap ( dokümanlara bakın ):
mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
connection.db.dropDatabase();
// alternatively:
// mongoose.connection.db.dropDatabase();
});
Bu kodu, firavun faresi 4.13.6 kullanarak kendi kodumda test ettim. Ayrıca, useMongoClient
seçeneğin kullanımına dikkat edin ( dokümanlara bakın ). Dokümanlar şunu gösterir:
Mongoose'un varsayılan bağlantı mantığı 4.11.0 itibarıyla kullanımdan kaldırılmıştır. Lütfen useMongoClient seçeneğini kullanarak yeni bağlantı mantığını seçin, ancak mevcut bir kod tabanını yükseltiyorsanız önce bağlantılarınızı test ettiğinizden emin olun!
Diğer çözümlerde yaşadığım zorluk, dizinlerin tekrar çalışmasını istiyorsanız, uygulamanızı yeniden başlatmaya dayanmalarıdır.
İhtiyaçlarım için (yani, tüm koleksiyonları bir birim testi çalıştırabilmek, ardından indeksleriyle birlikte yeniden oluşturabilmek), bu çözümü uyguladım:
Bu dayanıyor underscore.js ve async.js bu kitaplığa karşıyız ama geliştirici için bir kullanıcıta olarak bu bırakırsanız Parellel dizinleri birleştirmek için kütüphaneler, bu çözülmeye başladı.
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')
})
})
})
Bir veritabanındaki belirli bir koleksiyonu boşaltmak için:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
Not:
Bu benim için Mongoose olarak çalışıyor v4.7.0
:
mongoose.connection.dropDatabase();
Veritabanınızı Mongoose'a bırakmanın en iyi yolu, kullandığınız Mongoose sürümüne bağlıdır. Mongoose'un 4.6.4 veya daha yeni bir sürümünü kullanıyorsanız, o sürümde eklenen bu yöntem sizin için muhtemelen iyi çalışacaktır:
mongoose.connection.dropDatabase();
Daha eski sürümlerde bu yöntem mevcut değildi. Bunun yerine, doğrudan bir MongoDB araması kullanacaktınız:
mongoose.connection.db.dropDatabase();
Ancak, bu veritabanı bağlantısı oluşturulduktan hemen sonra çalıştırılırsa, sessizce başarısız olabilir. Bu, bağlantının asenkron olması ve komut gerçekleştiğinde henüz kurulmaması ile ilgilidir. Bu normalde .find()
, bağlantı açılana kadar kuyruğa girip ardından çalıştırılan diğer Mongoose çağrıları için bir sorun değildir .
İçin kaynak koduna bakarsanız dropDatabase()
Eklenen kısayolun tam olarak bu sorunu çözmek için tasarlandığını görebilirsiniz. Bağlantının açık ve hazır olup olmadığını kontrol eder. Eğer öyleyse, komutu hemen çalıştırır. Değilse, veritabanı bağlantısı açıldığında çalıştırılacak komutu kaydeder.
Önerilerden bazıları yukarıda tavsiye daima senin koyarak dropDatabase
komutunu open
işleyicisi. Ancak bu, yalnızca bağlantı henüz açılmadığında çalışır.
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;
};
İşte yukarıdaki mantığın daha önceki Mongoose sürümleriyle kullanılabilen basit bir sürümü:
// 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);
}
}
Firavun Faresi 4.6.0+:
mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
mongoose.connection.db.dropDatabase();
});
Bağlanmak için bir geri arama iletmek artık işe yaramayacak:
TypeError: null değerinin 'commandsTakeWriteConcern' özelliği okunamıyor
connect
ekleyebilmeniz .then((connection) => { ... });
için bir söz verir mongoose.connect
. Bakınız: mongoosejs.com/docs/connections.html
Mongoose kitaplığında kaldırma yöntemi amortismana tabi tutulduğundan, deleteMany işlevini hiçbir parametre geçirmeden kullanabiliriz.
Model.deleteMany();
Bu, bu belirli Modelin tüm içeriğini silecek ve koleksiyonunuz boş olacaktır.