Làm thế nào để loại bỏ cơ sở dữ liệu với Mongoose?


Câu trả lời:


166

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

Cảnh báo

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!


2
khi tôi cố gắng lựa chọn thứ hai tôi nhận được "không thể đọc được bất động sản 'collectionName' không xác định"
Yaron Naveh

1
Vì tất cả các bộ sưu tập đều nằm trong hash mongoose.connection.collections, bạn có thể chỉ cần liệt kê chúng cho (bộ sưu tập trong mongoose.connection.collections) {mongoose.connection.collections [collection] .drop} ... cũng tương tự
drinchev

3
Bạn mắc lỗi đánh máy - thêm dấu phẩy sau hàm (err) ... phải là: mongoose.connection.collections ['collectionName']. Drop (function (err) {console.log ('collection drop') ;});
arxpoetica

3
Tôi có phải là người duy nhất nhận ra rằng câu trả lời này không giải quyết câu hỏi làm thế nào để loại bỏ một cơ sở dữ liệu. Nó không yêu cầu để thả một bộ sưu tập hỏi của nó để thả một cơ sở dữ liệu ..
Joseph Persie

3
"Không có phương pháp nào để loại bỏ một bộ sưu tập từ mongoose", trước hết OP muốn xóa một cơ sở dữ liệu chứ không phải một cuộn giấy, thứ hai là câu trả lời của @hellslam dưới đây hoạt động tốt.
SCBuergel.eth

79

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

1
Tôi đã thử 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?
Freewind

Nếu bạn kết nối với nó sau đó, nó sẽ được tạo lại, mặc dù trống. Có bộ sưu tập nào trong đó sau khi bạn đánh rơi không?
hellslam

Bạn đang sử dụng cùng một kết nối hay tạo nhiều kết nối?
hellslam

12
Tôi thấy dropDatabaselời gọi nên được đặt trong lệnh gọi lại của connect, như mongoose.connect('...', function() { ...dropDatabase()}).
Freewind

1
dropDatabase dường như không làm việc trong một số trường hợp, nhưng lệnh Mongo trực tiếp vẫn có thể được sử dụng mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz

14

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ẻ =)


là nó có thể để giảm db với cái này? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy

2
Điều này rất hữu ích, cảm ơn! Tuy nhiên, tên biến của bạn hơi gây hiểu nhầm ... mongoose.connectthực sự trả về mongoose. Thay vì conn = mongoose.connect(...)tôi sẽ viết mongoose.connect(...)và sau đó conn = mongooose.connection.
một mọt sách trả tiền

Tôi không nghĩ rằng mã này sẽ luôn hoạt động vì connectkhô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 dropDatabaselệnh trong lệnh gọi lại connectcâu lệnh hoặc opentrình xử lý sự kiện.
Mark Stosberg

8

Đã 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


7

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 useMongoClienttù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ó!


5

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.jsasync.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')
    })
  })
})

4

Để 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ú:

  1. Chọn một mô hình tham chiếu đến lược đồ cụ thể (lược đồ tập hợp bạn muốn xóa).
  2. Thao tác này sẽ không xóa tên bộ sưu tập khỏi cơ sở dữ liệu.
  3. Thao tác này sẽ xóa tất cả các tài liệu trong một bộ sưu tập.


4

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 dropDatabaselệnh của bạn trong opentrì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);
    }
}  

2

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


1
connecttrả 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
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

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.


0

Để bỏ tất cả tài liệu vào một bộ sưu tập:

await mongoose.connection.db.dropDatabase();

Câu trả lời này dựa trên tệp mongoose index.d.ts:

dropDatabase(): Promise<any>;

-2

Để 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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.