Vấn đề ở đây là vòng lặp bạn đang chạy không đợi mỗi thao tác hoàn thành. Vì vậy, trên thực tế, bạn chỉ đang xếp hàng 1000 của .save()
yêu cầu và cố gắng chạy chúng đồng thời. Bạn không thể làm điều đó trong các giới hạn hợp lý, do đó bạn nhận được phản hồi lỗi.
async mô-đun có nhiều phương thức khác nhau để lặp lại trong khi xử lý lệnh gọi lại cho trình lặp đó, trong đó có thể là trực tiếp đơn giản nhất cho là trong khi . Mongoose cũng xử lý việc quản lý kết nối cho bạn mà không cần nhúng vào lệnh gọi lại, vì các mô hình nhận biết được kết nối:
var tempColSchema = new Schema({
cid: {
type: Number,
required: true
},
loc:[]
});
var TempCol = mongoose.model( "TempCol", tempColSchema );
mongoose.connect( 'mongodb://localhost/mean-dev' );
var i = 0;
async.whilst(
function() { return i < 10000000; },
function(callback) {
i++;
var c = i;
console.log(c);
var lon = parseInt(c/100000);
var lat = c%100000;
new Tempcol({cid: Math.random(), loc: [lon, lat]}).save(function(err){
callback(err);
});
},
function(err) {
// When the loop is complete or on error
}
);
Không phải là cách tuyệt vời nhất để làm điều đó, nó vẫn là viết một lần và bạn có thể sử dụng các phương pháp khác để "chi phối" các hoạt động đồng thời, nhưng điều này ít nhất sẽ không làm nổ tung ngăn xếp cuộc gọi.
Biểu mẫu MongoDB 2.6 trở lên, bạn có thể sử dụng API hoạt động hàng loạt để xử lý nhiều lần ghi cùng một lúc trên máy chủ. Vì vậy, quá trình này cũng tương tự, nhưng lần này bạn có thể gửi 1000 lần một lúc đến máy chủ trong một lần ghi và phản hồi, nhanh hơn nhiều:
var tempColSchema = new Schema({
cid: {
type: Number,
required: true
},
loc:[]
});
var TempCol = mongoose.model( "TempCol", tempColSchema );
mongoose.connect( 'mongodb://localhost/mean-dev' );
mongoose.on("open",function(err,conn) {
var i = 0;
var bulk = TempCol.collection.initializeOrderedBulkOp();
async.whilst(
function() { return i < 10000000; },
function(callback) {
i++;
var c = i;
console.log(c);
var lon = parseInt(c/100000);
var lat = c%100000;
bulk.insert({ "cid": Math.random(), "loc": [ lon, lat ] });
if ( i % 1000 == 0 ) {
bulk.execute(function(err,result) {
bulk = TempCol.collection.initializeOrderedBulkOp();
callback(err);
});
} else {
process.nextTick(callback);
}
},
function(err) {
// When the loop is complete or on error
// If you had a number not plainly divisible by 1000
if ( i % 1000 != 0 )
bulk.execute(function(err,result) {
// possibly check for errors here
});
}
);
});
Điều đó thực sự đang sử dụng các phương thức trình điều khiển gốc chưa được hiển thị trong mongoose, vì vậy cần phải chú ý thêm để đảm bảo kết nối khả dụng. Đó là một ví dụ nhưng không phải là cách duy nhất, nhưng điểm chính là "ma thuật" mongoose cho các kết nối không được tích hợp sẵn ở đây, vì vậy bạn nên chắc chắn rằng nó đã được thiết lập.
Bạn có một số lượng lớn các mục cần xử lý, nhưng đây không phải là trường hợp bạn nên gọi bulk.execute()
trong khối cuối cùng đó cũng như được hiển thị, nhưng nó phụ thuộc vào số phản hồi với mô-đun.
Điểm chính là không tăng chồng các hoạt động lên một kích thước không hợp lý và giữ cho việc xử lý bị giới hạn. Kiểm soát luồng ở đây cho phép các hoạt động sẽ mất một thời gian để thực sự hoàn thành trước khi chuyển sang lần lặp tiếp theo. Vì vậy, cập nhật hàng loạt hoặc một số xếp hàng song song bổ sung là những gì bạn muốn để có hiệu suất tốt nhất.
Ngoài ra còn có .initializeUnorderedBulkOp()
biểu mẫu cho điều này nếu bạn không muốn lỗi ghi nghiêm trọng nhưng thay vào đó hãy xử lý chúng theo một cách khác. Chủ yếu là xem tài liệu chính thức về Bulk API và phản hồi để biết cách diễn giải phản hồi được đưa ra.