ฉันกำลังเตรียมสคริปต์การสร้างฐานข้อมูลใน Node.js และ Mongoose ฉันจะตรวจสอบได้อย่างไรว่ามีฐานข้อมูลอยู่แล้วและถ้าเป็นเช่นนั้นให้วาง (ลบ) โดยใช้ Mongoose
ฉันไม่สามารถหาวิธีที่จะทิ้งพังพอนได้
ฉันกำลังเตรียมสคริปต์การสร้างฐานข้อมูลใน Node.js และ Mongoose ฉันจะตรวจสอบได้อย่างไรว่ามีฐานข้อมูลอยู่แล้วและถ้าเป็นเช่นนั้นให้วาง (ลบ) โดยใช้ Mongoose
ฉันไม่สามารถหาวิธีที่จะทิ้งพังพอนได้
คำตอบ:
ไม่มีวิธีการทิ้งคอลเลกชันจากพังพอนสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือลบเนื้อหาออก:
Model.remove({}, function(err) {
console.log('collection removed')
});
แต่มีวิธีในการเข้าถึงไดรเวอร์ javascript ดั้งเดิมของ mongodb ซึ่งสามารถใช้สำหรับสิ่งนี้ได้
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
สำรองข้อมูลก่อนลองทำในกรณีที่มีอะไรผิดพลาด!
พังพอนจะสร้างฐานข้อมูลหากไม่มีอยู่ในการเชื่อมต่อดังนั้นเมื่อคุณทำการเชื่อมต่อคุณสามารถสอบถามเพื่อดูว่ามีอะไรอยู่ในนั้นหรือไม่
คุณสามารถวางฐานข้อมูลใดก็ได้ที่คุณเชื่อมต่อ:
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();
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 ฉันพบสภาพการแข่งขันที่ทำให้การทดสอบของฉันกลับมา ในกรณีของฉันฉันกำลังใช้การทดสอบมอคค่าและในฟังก์ชัน before ของการทดสอบฉันต้องการลบ DB ทั้งหมด นี่คือสิ่งที่เหมาะกับฉัน
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();
});
ฉันทดสอบรหัสนี้ด้วยรหัสของฉันเองโดยใช้พังพอน 4.13.6 นอกจากนี้โปรดสังเกตการใช้useMongoClient
ตัวเลือก ( ดูเอกสาร ) เอกสารระบุ:
ตรรกะการเชื่อมต่อเริ่มต้นของ Mongoose เลิกใช้งานเมื่อ 4.11.0 โปรดเลือกใช้ตรรกะการเชื่อมต่อใหม่โดยใช้ตัวเลือก useMongoClient แต่ตรวจสอบให้แน่ใจว่าคุณได้ทดสอบการเชื่อมต่อของคุณก่อนหากคุณกำลังอัปเกรดโค้ดเบสที่มีอยู่!
ความยากลำบากที่ฉันมีกับวิธีแก้ปัญหาอื่น ๆ คือพวกเขาต้องพึ่งพาการรีสตาร์ทแอปพลิเคชันของคุณหากคุณต้องการให้ดัชนีทำงานอีกครั้ง
สำหรับความต้องการของฉัน (เช่นสามารถเรียกใช้การทดสอบหน่วย nukes คอลเล็กชันทั้งหมดจากนั้นสร้างขึ้นใหม่พร้อมกับดัชนีของพวกเขา) ฉันลงเอยด้วยการใช้โซลูชันนี้:
สิ่งนี้อาศัยไลบรารี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);
}
});
บันทึก:
สิ่งนี้ใช้ได้กับฉันในฐานะพังพอนv4.7.0
:
mongoose.connection.dropDatabase();
วิธีที่ดีที่สุดในการวางฐานข้อมูลของคุณใน Mongoose ขึ้นอยู่กับเวอร์ชันของ Mongoose ที่คุณใช้ หากคุณใช้ Mongoose เวอร์ชัน 4.6.4 หรือใหม่กว่าวิธีนี้ที่เพิ่มเข้ามาในรุ่นนั้นน่าจะใช้ได้ดีสำหรับคุณ:
mongoose.connection.dropDatabase();
ในรุ่นเก่าไม่มีวิธีนี้ แต่คุณต้องใช้การโทร MongoDB โดยตรง:
mongoose.connection.db.dropDatabase();
อย่างไรก็ตามหากรันหลังจากสร้างการเชื่อมต่อฐานข้อมูลแล้วการเชื่อมต่อฐานข้อมูลอาจล้มเหลวโดยไม่โต้ตอบ สิ่งนี้เกี่ยวข้องกับการเชื่อมต่อเป็นแบบอะซิงโครนัสและยังไม่ได้รับการตั้งค่าเมื่อคำสั่งเกิดขึ้น ปกตินี่ไม่ใช่ปัญหาสำหรับการเรียกพังพอนอื่น ๆ เช่น.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
beforeEach((done) => {
mongoose.connection.dropCollection('products',(error ,result) => {
if (error) {
console.log('Products Collection is not dropped')
} else {
console.log(result)
}
done()
})
})
เนื่องจากวิธีการลบเป็นค่าเสื่อมราคาในไลบรารีพังพอนเราจึงสามารถใช้ฟังก์ชัน deleteMany โดยไม่ผ่านพารามิเตอร์
Model.deleteMany();
การดำเนินการนี้จะลบเนื้อหาทั้งหมดของรุ่นนี้และคอลเล็กชันของคุณจะว่างเปล่า
ในการวางเอกสารทั้งหมดในคอลเลกชัน:
await mongoose.connection.db.dropDatabase();
คำตอบนี้อ้างอิงจากไฟล์ mongoose index.d.ts:
dropDatabase(): Promise<any>;