如果您的MongoDB服務器是2.6或更新版本,這將是更好地利用使用寫的好處命令Bulk API,允許批量執行update
操作,這些操作都只需在服務器之上的抽象,使很容易構建批量操作。這些批量操作來主要有兩種形式:
- 有序批量操作。這些操作按順序執行所有操作,並在第一次寫入錯誤時出錯。
- 無序批量操作。這些操作並行執行所有操作並聚合所有錯誤。無序批量操作不保證執行順序。
請注意,對於比2.6更早的服務器,API將下載轉換操作。然而,它不可能下變換100%,因此可能會出現一些無法正確報告正確數字的邊緣情況。
對於你的三個常見的使用情況,您可以實現這樣的大宗原料藥:
案例1.更改類型的屬性值,在不改變值:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;
// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;
// Case 1. Change type of value of property, without changing the value.
col.find({"timestamp": {"$exists": true, "$type": 2} }).each(function (err, doc) {
var newTimestamp = parseInt(doc.timestamp);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "timestamp": newTimestamp }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});
if (counter % 1000 != 0){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});
案例2.根據現有物業的價值添加新房產:
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;
// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;
// Case 2. Add new property based on value of existing property.
col.find({"name": {"$exists": false } }).each(function (err, doc) {
var fullName = doc.firstname + " " doc.lastname;
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "name": fullName }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});
if (counter % 1000 != 0){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});
第3種情況。只需添加文檔中的刪除屬性即可。
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;
// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;
// Case 3. Simply adding removing properties from documents.
col.find({"street_no": {"$exists": true } }).each(function (err, doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "no": doc.street_no },
"$unset": { "street_no": "" }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});
if (counter % 1000 != 0){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});
完美,謝謝chridam,錯過了大宗原料藥 – ezmilhouse
建議加快代碼:(1)使用有限的投影上的搜索查詢,如果你只需要輕按一個領域,設置投影對於這一領域而言,這將加速在線上提供文檔。 (2)正如@chridam所提到的,使用UnorderedBulkOp並行更新,所以速度更快。 – marmor