จะวางฐานข้อมูลด้วยพังพอนได้อย่างไร?


99

ฉันกำลังเตรียมสคริปต์การสร้างฐานข้อมูลใน Node.js และ Mongoose ฉันจะตรวจสอบได้อย่างไรว่ามีฐานข้อมูลอยู่แล้วและถ้าเป็นเช่นนั้นให้วาง (ลบ) โดยใช้ Mongoose

ฉันไม่สามารถหาวิธีที่จะทิ้งพังพอนได้


คำตอบ:


168

ไม่มีวิธีการทิ้งคอลเลกชันจากพังพอนสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือลบเนื้อหาออก:

Model.remove({}, function(err) { 
   console.log('collection removed') 
});

แต่มีวิธีในการเข้าถึงไดรเวอร์ javascript ดั้งเดิมของ mongodb ซึ่งสามารถใช้สำหรับสิ่งนี้ได้

mongoose.connection.collections['collectionName'].drop( function(err) {
    console.log('collection dropped');
});

คำเตือน

สำรองข้อมูลก่อนลองทำในกรณีที่มีอะไรผิดพลาด!


2
เมื่อฉันลองตัวเลือกที่สองฉันได้รับ "can't read property 'collectionName' of undefined"
Yaron Naveh

1
เนื่องจากคอลเล็กชันทั้งหมดอยู่ในแฮช mongoose.connection.collections คุณจึงสามารถระบุรายการ (collection in mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ...
smth similar

3
คุณพิมพ์ผิด - เครื่องหมายจุลภาคพิเศษหลังฟังก์ชัน (err) ... ควรเป็น: mongoose.connection.collections ['collectionName']. drop (function (err) {console.log ('collection drop') ;});
arxpoetica

3
ฉันเป็นคนเดียวที่รู้คำตอบนี้ไม่ได้ตอบคำถามว่าจะวางฐานข้อมูลได้อย่างไร ไม่ขอทิ้งคอลเลกชัน แต่ขอให้วางฐานข้อมูล ..
Joseph Persie

3
"ไม่มีวิธีใดในการทิ้งคอลเลกชันจากพังพอน" ก่อนอื่น OP ต้องการลบฐานข้อมูลไม่ใช่ colledtion ประการที่สองคำตอบของ @hellslam ด้านล่างใช้ได้ดี
SCBuergel.eth

81

พังพอนจะสร้างฐานข้อมูลหากไม่มีอยู่ในการเชื่อมต่อดังนั้นเมื่อคุณทำการเชื่อมต่อคุณสามารถสอบถามเพื่อดูว่ามีอะไรอยู่ในนั้นหรือไม่

คุณสามารถวางฐานข้อมูลใดก็ได้ที่คุณเชื่อมต่อ:

var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
    /* Drop the DB */
    mongoose.connection.db.dropDatabase();
});

1
ฉันลองแล้วmongoose.connection.db.dropDatabase()แต่ฉันพบว่าฐานข้อมูลยังอยู่? ฉันคิดถึงอะไร?
Freewind

หากคุณเชื่อมต่อหลังจากนั้นระบบจะสร้างขึ้นใหม่แม้ว่าจะว่างเปล่า มีคอลเลกชันใดบ้างหลังจากที่คุณทำหล่น
hellslam

คุณใช้การเชื่อมต่อเดียวกันตลอดหรือสร้างการเชื่อมต่อหลายรายการ?
hellslam

12
ผมพบว่าdropDatabaseการภาวนาควรจะอยู่ในการติดต่อกลับของเป็นconnect mongoose.connect('...', function() { ...dropDatabase()})
Freewind

1
ดูเหมือนว่า dropDatabase ไม่ทำงานในบางกรณี แต่ยังสามารถใช้คำสั่ง mongo โดยตรงได้ mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz

14

หากคุณแก้ไขโซลูชันของ @ 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 ด้วยสิ่งนี้ db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy

2
สิ่งนี้มีประโยชน์ขอบคุณ! อย่างไรก็ตามชื่อตัวแปรของคุณจะทำให้เข้าใจผิดเล็ก ๆ น้อย ๆ ... จริงผลตอบแทนmongoose.connect mongooseแทนที่จะconn = mongoose.connect(...)ฉันเขียนแล้วmongoose.connect(...) conn = mongooose.connection
เนิร์ดจ่าย

ฉันไม่คิดว่ารหัสนี้จะใช้ได้เสมอไปเพราะconnectเป็นแบบอะซิงโครนัส ดังนั้นหากการเชื่อมต่อไม่เกิดขึ้นทันทีคำสั่ง dropDatabase () จะล้มเหลว นั่นเป็นเหตุผลที่โซลูชันอื่น ๆ ข้างต้นแนะนำให้ใส่dropDatabaseคำสั่งในการเรียกกลับไปที่connectคำสั่งหรือopenตัวจัดการเหตุการณ์
Mark Stosberg

8

ลองคำตอบของ @ 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


7

คำตอบที่อัปเดตสำหรับ 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 แต่ตรวจสอบให้แน่ใจว่าคุณได้ทดสอบการเชื่อมต่อของคุณก่อนหากคุณกำลังอัปเกรดโค้ดเบสที่มีอยู่!


5

ความยากลำบากที่ฉันมีกับวิธีแก้ปัญหาอื่น ๆ คือพวกเขาต้องพึ่งพาการรีสตาร์ทแอปพลิเคชันของคุณหากคุณต้องการให้ดัชนีทำงานอีกครั้ง

สำหรับความต้องการของฉัน (เช่นสามารถเรียกใช้การทดสอบหน่วย 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')
    })
  })
})

4

ในการล้างคอลเลกชันเฉพาะในฐานข้อมูล:

model.remove(function(err, p){
    if(err){ 
        throw err;
    } else{
        console.log('No Of Documents deleted:' + p);
    }
});

บันทึก:

  1. เลือกโมเดลที่อ้างถึงสคีมาเฉพาะ (สคีมาของคอลเลกชันที่คุณต้องการลบ)
  2. การดำเนินการนี้จะไม่ลบชื่อคอลเล็กชันออกจากฐานข้อมูล
  3. ซึ่งจะลบเอกสารทั้งหมดในคอลเล็กชัน


4

วิธีที่ดีที่สุดในการวางฐานข้อมูลของคุณใน 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);
    }
}  

2

พังพอน 4.6.0+:

mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
    mongoose.connection.db.dropDatabase();
});

การส่งการโทรกลับเพื่อเชื่อมต่อจะใช้ไม่ได้อีกต่อไป:

TypeError: ไม่สามารถอ่านคุณสมบัติ 'commandTakeWriteConcern' ของ null


1
connectส่งคืนคำสัญญาเพื่อให้คุณสามารถเพิ่มลง.then((connection) => { ... });ในไฟล์mongoose.connect. ดู: mongoosejs.com/docs/connections.html
Andre M

1
beforeEach((done) => {
      mongoose.connection.dropCollection('products',(error ,result) => {
      if (error) {
        console.log('Products Collection is not dropped')
      } else {
        console.log(result)
      }
    done()
    })
  })

0

เนื่องจากวิธีการลบเป็นค่าเสื่อมราคาในไลบรารีพังพอนเราจึงสามารถใช้ฟังก์ชัน deleteMany โดยไม่ผ่านพารามิเตอร์

Model.deleteMany();

การดำเนินการนี้จะลบเนื้อหาทั้งหมดของรุ่นนี้และคอลเล็กชันของคุณจะว่างเปล่า


0

ในการวางเอกสารทั้งหมดในคอลเลกชัน:

await mongoose.connection.db.dropDatabase();

คำตอบนี้อ้างอิงจากไฟล์ mongoose index.d.ts:

dropDatabase(): Promise<any>;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.