Chèn hàng loạt Mongoose (mongodb)?


114

Liệu Mongoose v3.6 + hỗ trợ hàng loạt chen bây giờ? Tôi đã tìm kiếm trong vài phút nhưng bất kỳ thứ gì phù hợp với truy vấn này đều có tuổi đời vài năm và câu trả lời là không rõ ràng.

Biên tập:

Để tham khảo trong tương lai, câu trả lời là sử dụng Model.create(). create()chấp nhận một mảng làm đối số đầu tiên của nó, vì vậy bạn có thể truyền tài liệu của mình để được chèn dưới dạng một mảng.

Xem tài liệu Model.create ()


Xem câu trả lời này cho câu hỏi trước.
JohnnyHK

Cảm ơn. Đó là những gì tôi đã tìm thấy sau khi đăng.
Geuis

@Geuis vui lòng thêm chỉnh sửa của bạn làm câu trả lời và chấp nhận nó để giải quyết câu hỏi của bạn.
Filip Dupanović


Model.create () chậm và nếu bạn đang cân nhắc việc chèn một số lượng lớn tài liệu, tốt hơn nên thực hiện phương pháp này .
Lucio Paiva

Câu trả lời:


162

Model.create () so với Model.collection.insert (): một cách tiếp cận nhanh hơn

Model.create()là một cách không tốt để thực hiện chèn nếu bạn đang xử lý một số lượng lớn rất lớn. Nó sẽ rất chậm . Trong trường hợp đó, bạn nên sử dụng Model.collection.insert, nó hoạt động tốt hơn nhiều . Tùy thuộc vào kích thước của số lượng lớn, Model.create()thậm chí sẽ sụp đổ! Đã thử với một triệu tài liệu, không có may mắn. Sử dụng Model.collection.insertnó chỉ mất vài giây.

Model.collection.insert(docs, options, callback)
  • docs là mảng tài liệu sẽ được chèn vào;
  • optionslà một đối tượng cấu hình tùy chọn - xem tài liệu
  • callback(err, docs)sẽ được gọi sau khi tất cả các tài liệu được lưu hoặc xảy ra lỗi. Về thành công, tài liệu là mảng các tài liệu tồn tại.

Như tác giả của Mongoose đã chỉ ra ở đây , phương pháp này sẽ bỏ qua bất kỳ quy trình xác thực nào và truy cập trực tiếp vào trình điều khiển Mongo. Đó là một sự đánh đổi bạn phải thực hiện vì bạn đang xử lý một lượng lớn dữ liệu, nếu không, bạn sẽ không thể chèn nó vào cơ sở dữ liệu của mình (hãy nhớ rằng chúng ta đang nói đến hàng trăm nghìn tài liệu ở đây).

Một ví dụ đơn giản

var Potato = mongoose.model('Potato', PotatoSchema);

var potatoBag = [/* a humongous amount of potato objects */];

Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

Cập nhật 2019-06-22 : mặc dù insert()vẫn có thể được sử dụng tốt nhưng nó đã không còn được ưu tiên insertMany()nữa. Các tham số hoàn toàn giống nhau, vì vậy bạn chỉ có thể sử dụng nó như một sự thay thế thả vào và mọi thứ sẽ hoạt động tốt (tốt, giá trị trả về hơi khác một chút, nhưng bạn có thể không sử dụng nó).

Tài liệu tham khảo



Hãy cho ví dụ với Mongoose.
Steve K

15
Model.collectionđi trực tiếp qua trình điều khiển Mongo, bạn sẽ mất tất cả nội dung mongoose gọn gàng bao gồm xác nhận và móc. Chỉ là một thứ để ghi nhớ trong đầu. Model.createmất móc, nhưng vẫn trải qua quá trình xác thực. Nếu bạn muốn nó hết, bạn phải lặp vànew MyModel()
Pier-Luc Gendreau

1
@ Pier-LucGendreau Bạn hoàn toàn đúng, nhưng bạn phải đánh đổi một khi bắt đầu xử lý một lượng lớn dữ liệu.
Lucio Paiva

1
Hãy cẩn thận với độc giả mới: "Đã thay đổi trong phiên bản 2.6: Chèn chèn () trả về một đối tượng có chứa trạng thái của hoạt động". Không có thêm tài liệu.
Mark Ni

117

Mongoose 4.4.0 hiện hỗ trợ chèn hàng loạt

Mongoose 4.4.0 giới thiệu --true-- chèn số lượng lớn với phương thức mô hình .insertMany(). Nó nhanh hơn cách lặp lại .create()hoặc cung cấp cho nó một mảng.

Sử dụng:

var rawDocuments = [/* ... */];

Book.insertMany(rawDocuments)
    .then(function(mongooseDocuments) {
         /* ... */
    })
    .catch(function(err) {
        /* Error handling */
    });

Hoặc là

Book.insertMany(rawDocuments, function (err, mongooseDocuments) { /* Your callback function... */ });

Bạn có thể theo dõi nó trên:


2
Tại thời điểm này, phương pháp này không hỗ trợ tùy chọn.
Amri

Cảm ơn bạn đã trả lời. Bất kỳ ý tưởng nào nên phân tích cú pháp của các tài liệu thô? Tôi đã thử nó với một mảng các đối tượng Json và tất cả những gì nó đã chèn chỉ là ID của chúng. :(
Ondrej Tokar

4
Làm thế nào là điều này khác với bulkWrite? Xem ở đây: stackoverflow.com/questions/38742475/…
Ondrej Tokar

insertMany không làm việc cho tôi. Tôi có một fatal error allocation failed. Nhưng nếu tôi sử dụng collection.insert Nó hoạt động hoàn hảo.
John

Điều này có hoạt động với những thứ bổ sung mà lược đồ mongoose cung cấp không? ví dụ: điều này sẽ thêm dữ liệu nếu không có ngày tồn tạidateCreated : { type: Date, default: Date.now },
jack trống

22

Thật vậy, bạn có thể sử dụng phương thức "create" của Mongoose, nó có thể chứa một mảng tài liệu, hãy xem ví dụ sau:

Candy.create({ candy: 'jelly bean' }, { candy: 'snickers' }, function (err, jellybean, snickers) {
});

Chức năng gọi lại chứa các tài liệu đã chèn. Không phải lúc nào bạn cũng biết có bao nhiêu mục phải được chèn (độ dài đối số cố định như trên) để bạn có thể lặp qua chúng:

var insertedDocs = [];
for (var i=1; i<arguments.length; ++i) {
    insertedDocs.push(arguments[i]);
}

Cập nhật: Một giải pháp tốt hơn

Một giải pháp tốt hơn sẽ sử dụng Candy.collection.insert()thay vì Candy.create()- được sử dụng trong ví dụ trên - vì nó nhanh hơn ( create()đang gọi Model.save()từng mục nên chậm hơn).

Xem tài liệu Mongo để biết thêm thông tin: http://docs.mongodb.org/manual/reference/method/db.collection.insert/

(cảm ơn arcseldon đã chỉ ra điều này)


groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds - Tùy thuộc vào những gì bạn muốn, liên kết có tùy chọn tốt hơn.
arcseldon

Ý bạn không phải là {type:'jellybean'}thay vì {type:'jelly bean'}sao? Btw. những loại kỳ lạ đó là gì? Chúng có phải là một phần của Mongoose API không?
Steve K

2
Chà, đó là một lựa chọn đặt tên tồi, vì typethường được dành riêng trong Mongoose để biểu thị ADT của đối tượng cơ sở dữ liệu.
Steve K

2
@sirbenbenji Tôi đã thay đổi nó, nhưng nó là một ví dụ cũng có trong tài liệu chính thức. Tôi nghĩ điều này không cần thiết phải tán thành.
benske

1
Bằng cách giải quyết tài sản .collection bạn đang bỏ qua Mongoose (xác nhận, 'trước' phương pháp ...)
Derek

4

Bạn có thể thực hiện chèn hàng loạt bằng cách sử dụng trình bao mongoDB bằng cách chèn các giá trị trong một mảng.

db.collection.insert([{values},{values},{values},{values}]);

có cách nào trong mongoose để chèn số lượng lớn không?
SUNDARRAJAN K

1
YourModel.collection.insert()
Bill Dami

Bằng cách giải quyết tài sản .collection bạn đang bỏ qua Mongoose (xác nhận, 'trước' phương pháp ...)
Derek

Đây không phải là mongoose, và collection.insertcâu trả lời thô đã được đưa ra vài tuần trước câu trả lời này và được giải thích chi tiết hơn nhiều.
Dan Dascalescu

4

Bạn có thể thực hiện chèn hàng loạt bằng cách sử dụng mongoose, là câu trả lời cho điểm cao nhất. Nhưng ví dụ không thể hoạt động, nó phải là:

/* a humongous amount of potatos */
var potatoBag = [{name:'potato1'}, {name:'potato2'}];

var Potato = mongoose.model('Potato', PotatoSchema);
Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

Không sử dụng một phiên bản lược đồ cho chèn hàng loạt, bạn nên sử dụng một đối tượng bản đồ thuần túy.


Câu trả lời đầu tiên không sai, nó chỉ có xác nhận
Lucatylesb

1
Bằng cách giải quyết tài sản .collection bạn đang bỏ qua Mongoose (xác nhận, 'trước' phương pháp ...)
Derek

4

Đây là cả hai cách tiết kiệm dữ liệu với insertMany và save

1) Mongoose lưu mảng tài liệu với insertManysố lượng lớn

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const data = [/* array of object which data need to save in db */];

    Potato.insertMany(data)  
    .then((result) => {
            console.log("result ", result);
            res.status(200).json({'success': 'new documents added!', 'data': result});
    })
    .catch(err => {
            console.error("error ", err);
            res.status(400).json({err});
    });
})

2) Mongoose lưu mảng tài liệu với .save()

Các tài liệu này sẽ lưu song song.

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const saveData = []
    const data = [/* array of object which data need to save in db */];
    data.map((i) => {
        console.log(i)
        var potato = new Potato(data[i])
        potato.save()
        .then((result) => {
            console.log(result)
            saveData.push(result)
            if (saveData.length === data.length) {
                res.status(200).json({'success': 'new documents added!', 'data': saveData});
            }
        })
        .catch((err) => {
            console.error(err)
            res.status(500).json({err});
        })
    })
})

3

Có vẻ như việc sử dụng mongoose có giới hạn hơn 1000 tài liệu, khi sử dụng

Potato.collection.insert(potatoBag, onInsert);

Bạn có thể dùng:

var bulk = Model.collection.initializeOrderedBulkOp();

async.each(users, function (user, callback) {
    bulk.insert(hash);
}, function (err) {
    var bulkStart = Date.now();
    bulk.execute(function(err, res){
        if (err) console.log (" gameResult.js > err " , err);
        console.log (" gameResult.js > BULK TIME  " , Date.now() - bulkStart );
        console.log (" gameResult.js > BULK INSERT " , res.nInserted)
      });
});

Nhưng điều này nhanh hơn gần gấp đôi khi thử nghiệm với 10000 tài liệu:

function fastInsert(arrOfResults) {
var startTime = Date.now();
    var count = 0;
    var c = Math.round( arrOfResults.length / 990);

    var fakeArr = [];
    fakeArr.length = c;
    var docsSaved = 0

    async.each(fakeArr, function (item, callback) {

            var sliced = arrOfResults.slice(count, count+999);
            sliced.length)
            count = count +999;
            if(sliced.length != 0 ){
                    GameResultModel.collection.insert(sliced, function (err, docs) {
                            docsSaved += docs.ops.length
                            callback();
                    });
            }else {
                    callback()
            }
    }, function (err) {
            console.log (" gameResult.js > BULK INSERT AMOUNT: ", arrOfResults.length, "docsSaved  " , docsSaved, " DIFF TIME:",Date.now() - startTime);
    });
}

1
Bằng cách giải quyết tài sản .collection bạn đang bỏ qua Mongoose (xác nhận, 'trước' phương pháp ...)
Derek

0

Chia sẻ mã làm việc và có liên quan từ dự án của chúng tôi:

//documentsArray is the list of sampleCollection objects
sampleCollection.insertMany(documentsArray)  
    .then((res) => {
        console.log("insert sampleCollection result ", res);
    })
    .catch(err => {
        console.log("bulk insert sampleCollection error ", err);
    });

Các .insertManygiải pháp đã được trao (và giải thích) trong này 2016 câu trả lời .
Dan Dascalescu
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.