Bagaimana cara menjatuhkan database dengan Mongoose?

97

Saya sedang mempersiapkan skrip pembuatan database di Node.js dan Mongoose. Bagaimana cara memeriksa apakah database sudah ada, dan jika demikian, hapus (hapus) menggunakan Mongoose?

Saya tidak dapat menemukan cara untuk menjatuhkannya dengan luwak.

Yaron Naveh
sumber

Jawaban:

166

Tidak ada metode untuk membuang koleksi dari luwak, hal terbaik yang dapat Anda lakukan adalah menghapus salah satu konten:

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

Tetapi ada cara untuk mengakses driver javascript asli mongodb, yang dapat digunakan untuk ini

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

Peringatan

Buat cadangan sebelum mencoba ini jika terjadi kesalahan!

drinchev
sumber
2
ketika saya mencoba opsi kedua saya mendapatkan "tidak dapat membaca properti 'collectionName' dari undefined"
Yaron Naveh
1
Karena semua koleksi ada di hash mongoose.connection.collections, Anda dapat mencantumkannya untuk (koleksi di mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ...
smth
3
Anda salah ketik - koma tambahan setelah fungsi (err) ... seharusnya: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
arxpoetica
3
Apakah saya satu-satunya yang menyadari bahwa jawaban ini tidak menjawab pertanyaan tentang cara menjatuhkan database. Ini tidak meminta untuk membuang koleksi itu meminta untuk menjatuhkan database ..
Joseph Persie
3
"Tidak ada metode untuk menjatuhkan koleksi dari luwak", pertama-tama OP ingin menghapus database, bukan colledtion, kedua jawaban @hellslam di bawah berfungsi dengan baik.
SCBuergel.eth
79

Mongoose akan membuat database jika belum ada pada koneksi, jadi setelah Anda membuat koneksi, Anda bisa menanyakannya untuk melihat apakah ada sesuatu di dalamnya.

Anda dapat menjatuhkan database apa pun yang Anda sambungkan:

var mongoose = require('mongoose');
/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){
    /* Drop the DB */
    mongoose.connection.db.dropDatabase();
});
neraka
sumber
1
Saya mencoba mongoose.connection.db.dropDatabase()tetapi saya menemukan db masih ada? Apakah saya melewatkan sesuatu?
Freewind
Jika Anda terhubung dengannya setelah itu, itu akan dibuat ulang, meskipun kosong. Apakah ada koleksi di dalamnya setelah Anda menjatuhkannya?
hellslam
Apakah Anda menggunakan koneksi yang sama, atau membuat banyak koneksi?
hellslam
12
Saya menemukan dropDatabasepemanggilan harus ditempatkan di callback connect, sebagai mongoose.connect('...', function() { ...dropDatabase()}).
Freewind
1
dropDatabase tampaknya tidak berfungsi dalam beberapa kasus, tetapi perintah mongo langsung masih dapat digunakan mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz
14

Jika Anda memodifikasi solusi @ hellslam seperti ini, maka itu akan berhasil

Saya menggunakan teknik ini untuk menjatuhkan Database setelah tes integrasi saya

//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();

Setidaknya HTH itu untuk saya, jadi saya memutuskan untuk berbagi =)

silverfighter
sumber
apakah mungkin untuk menjatuhkan db dengan ini? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy
2
Ini sangat membantu, terima kasih! Namun, nama variabel Anda sedikit menyesatkan ... mongoose.connectsebenarnya kembali mongoose. Alih-alih conn = mongoose.connect(...)saya akan menulis mongoose.connect(...)dan kemudian conn = mongooose.connection.
seorang kutu buku yang dibayar
Saya tidak berpikir kode ini akan selalu berfungsi karena connectasynchronous. Jadi jika koneksi tidak segera terjadi, perintah dropDatabase () akan gagal. Itulah mengapa solusi lain di atas merekomendasikan untuk meletakkan dropDatabaseperintah di callback ke connectpernyataan atau openpenanganan peristiwa.
Mark Stosberg
8

Mencoba jawaban @ hellslam dan @ silverfighter. Saya menemukan kondisi balapan yang menahan tes saya. Dalam kasus saya, saya menjalankan tes mocha dan dalam fungsi tes sebelumnya saya ingin menghapus seluruh DB. Inilah yang berhasil untuk saya.

var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
    con.connection.db.dropDatabase(function(err, result){
        done();
    });
});

Anda dapat membaca lebih lanjut https://github.com/Automattic/mongoose/issues/1469

zafrani
sumber
7

Jawaban yang diperbarui, untuk 4.6.0+, jika Anda memiliki preferensi untuk promise ( lihat dokumen ):

mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
   connection.db.dropDatabase();
   // alternatively:
   // mongoose.connection.db.dropDatabase();
});

Saya menguji kode ini dalam kode saya sendiri, menggunakan luwak 4.13.6. Juga, perhatikan penggunaan useMongoClientopsi ( lihat dokumen ). Dokumen menunjukkan:

Logika koneksi default Mongoose tidak digunakan lagi mulai 4.11.0. Silakan ikut serta ke logika koneksi baru menggunakan opsi useMongoClient, tetapi pastikan Anda menguji koneksi Anda terlebih dahulu jika Anda meningkatkan basis kode yang ada!

Andre M
sumber
5

Kesulitan yang saya alami dengan solusi lain adalah mereka mengandalkan memulai ulang aplikasi Anda jika Anda ingin indeks berfungsi kembali.

Untuk kebutuhan saya (yaitu dapat menjalankan pengujian unit pada nukes semua koleksi, kemudian membuatnya kembali bersama dengan indeksnya), saya akhirnya menerapkan solusi ini:

Ini bergantung pada pustaka underscore.js dan async.js untuk mengumpulkan indeks dalam parellel, itu bisa dibatalkan jika Anda menentang pustaka itu tetapi saya membiarkannya sebagai latihan untuk pengembang.

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')
    })
  })
})
Eric Caron
sumber
4

Untuk mengosongkan koleksi tertentu dalam database:

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

catatan:

  1. Pilih model yang mengacu pada skema tertentu (skema koleksi yang ingin Anda hapus).
  2. Operasi ini tidak akan menghapus nama koleksi dari database.
  3. Ini menghapus semua dokumen dalam koleksi.
Orang Denmark
sumber
4

Ini bekerja untuk saya pada Mongoose v4.7.0:

mongoose.connection.dropDatabase();
pengguna3344977
sumber
4

Cara terbaik untuk meletakkan database Anda di Mongoose bergantung pada versi Mongoose yang Anda gunakan. Jika Anda menggunakan versi Mongoose 4.6.4 atau yang lebih baru, maka metode yang ditambahkan dalam rilis tersebut kemungkinan akan berfungsi dengan baik untuk Anda:

mongoose.connection.dropDatabase();

Dalam rilis yang lebih lama, metode ini tidak ada. Sebagai gantinya, Anda akan menggunakan panggilan MongoDB langsung:

mongoose.connection.db.dropDatabase();

Namun, jika ini dijalankan tepat setelah koneksi database dibuat, itu mungkin bisa gagal secara diam-diam. Ini terkait dengan koneksi yang sebenarnya asynchronous dan belum diatur ketika perintah terjadi. Ini biasanya tidak menjadi masalah untuk panggilan Mongoose lainnya seperti.find() , yang mengantri sampai koneksi terbuka dan kemudian dijalankan.

Jika Anda melihat kode sumber untuk dropDatabase() pintasan yang ditambahkan, Anda dapat melihat bahwa itu dirancang untuk menyelesaikan masalah ini dengan tepat. Ia memeriksa untuk melihat apakah koneksi terbuka dan siap. Jika demikian, itu akan segera mengaktifkan perintah. Jika tidak, ini mendaftarkan perintah untuk dijalankan ketika koneksi database telah dibuka.

Beberapa saran di atas merekomendasikan untuk selalu meletakkan dropDatabaseperintah Anda di openhandler. Tapi itu hanya berfungsi jika koneksi belum terbuka.

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;
};

Berikut adalah versi sederhana dari logika di atas yang dapat digunakan dengan versi Mongoose sebelumnya:

// 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);
    }
}  
Mark Stosberg
sumber
2

Luwak 4.6.0+:

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

Meneruskan panggilan balik untuk terhubung tidak akan berfungsi lagi:

TypeError: Tidak dapat membaca properti 'commandsTakeWriteConcern' dari null

Rayjax
sumber
1
connectmengembalikan janji, sehingga Anda dapat menambahkan .then((connection) => { ... });ke mongoose.connect. Lihat: 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()
    })
  })
Revt A
sumber
0

Karena metode penghapusan disusutkan di perpustakaan luwak, kita dapat menggunakan fungsi deleteMany tanpa parameter yang dilewatkan.

Model.deleteMany();

Ini akan menghapus semua konten Model khusus ini dan koleksi Anda akan kosong.

SAYAM.S SANGHVI
sumber
0

Untuk meletakkan semua dokumen dalam koleksi:

await mongoose.connection.db.dropDatabase();

Jawaban ini didasarkan dari file index.d.ts luwak:

dropDatabase(): Promise<any>;
mrhid3f.dll
sumber
-2

Untuk menjatuhkan semua dokumen dalam koleksi:

myMongooseModel.collection.drop();

seperti yang terlihat dalam tes

Sgnl
sumber