ezm*_*use 2 javascript mongodb node.js
我想最有效地更新大量(> 100,000)文档.
我的第一个天真的方法是在JS级别上进行,编写首先获取_ids的脚本,然后遍历_ids并通过_id(完整文档或$ set patch)调用更新.
我遇到了内存问题,还将数据分成最大块.500个文档(打开和关闭连接)似乎不能很好地工作.
那么我怎样才能在MongoDB级别上解决这个问题呢?
最佳实践?
我有3个常见用例,通常是维护工作流程:
1.更改属性值的类型,而不更改值.
// before
{
timestamp : '1446987395'
}
// after
{
timestamp : 1446987395
}Run Code Online (Sandbox Code Playgroud)
2.根据现有属性的值添加新属性.
// before
{
firstname : 'John',
lastname : 'Doe'
}
// after
{
firstname : 'John',
lastname : 'Doe',
name : 'John Doe'
}Run Code Online (Sandbox Code Playgroud)
3.只需从文档中添加删除属性.
// before
{
street : 'Whatever Ave',
street_no : '1025'
}
// after
{
street : 'Whatever Ave',
no : '1025'
}Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助.
如果您的MongoDB服务器是2.6或更高版本,最好利用写命令批量API,允许执行批量update操作,这些操作只是服务器顶部的抽象,以便轻松构建批量操作.这些批量操作主要有两种形式:
请注意,对于比2.6更旧的服务器,API将下转换操作.然而,不可能将100%下转换,因此可能存在一些无法正确报告正确数字的边缘情况.
对于您的三个常见用例,您可以像这样实现批量API:
案例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();
});
}
});
Run Code Online (Sandbox Code Playgroud)
案例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();
});
}
});
Run Code Online (Sandbox Code Playgroud)
案例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();
});
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4137 次 |
| 最近记录: |