这是一种在mongodb中插入和更新对象数组的安全方法吗?

时间:2016-08-17 13:05:36

标签: node.js mongodb

以下代码更新指定对象的数组,如果对象不在数据库中,则插入。它工作正常,但我是mongodb的新手,我不确定这是否安全或快速。

也许我应该使用updateMany?我尝试使用它,但我无法获得与以下代码相同的行为。

mongodb.connect(mongo_url, function(err, db) {
    if(err) console.log(err)
    else {
        var mongo_products_collection = db.collection("products")

        mongoUpsert(mongo_products_collection, data_products, function() {
            db.close()
        })
    }
})

function mongoUpsert(collection, data_array, cb) {
    var data_length = data_array.length

    for (var i=0; i < data_length; i++) {
        collection.update(
            {product_id: data_array[i].product_id},
            data_array[i],
            {upsert: true}
        )
    }

    return cb(false)
}

1 个答案:

答案 0 :(得分:3)

使用 bulkWrite API执行更新会更好地处理

mongodb.connect(mongo_url, function(err, db) {
    if(err) console.log(err)
    else {
        var mongo_products_collection = db.collection("products")

        mongoUpsert(mongo_products_collection, data_products, function() {
            db.close()
        })
    }
})

function mongoUpsert(collection, data_array, cb) {

    var bulkUpdateOps = data_array.map(function(data) {
        return {
            "updateOne": {
                "filter": { 
                    "product_id": data.product_id,
                    "post_modified": { "$ne": data.post_modified }
                },
                "update": { "$set": data },
                "upsert": true
            }
        };
    });

    collection.bulkWrite(bulkUpdateOps, function(err, r) {
        // do something with result
    });

    return cb(false);
}

如果你正在处理更大的数组,即&gt; 1000然后考虑将批量写入服务器的500个写入服务器,这样可以提供更好的性能,因为您没有向服务器发送每个请求,每500个请求只发送一次。

对于批量操作,MongoDB每批执行default internal limit 1000次操作,因此在您对批量大小有一定控制权而不是让MongoDB强加默认值时,选择500个文档是好的,即<幅度>的大型操作1000份文件。因此,对于第一种方法中的上述情况,可以立即写入所有数组,因为它很小,但500选择适用于较大的数组。

var ops = [],
    counter = 0;

data_array.forEach(function(data) {
    ops.push({
        "updateOne": {
            "filter": { 
                "product_id": data.product_id, 
                "post_modified": { "$ne": data.post_modified } 
            },
            "update": { "$set": data },
            "upsert": true
        }
    });
    counter++;

    if (counter % 500 == 0) {
        collection.bulkWrite(ops, function(err, r) {
            // do something with result
        });
        ops = [];
    }
})

if (counter % 500 != 0) {
    collection.bulkWrite(ops, function(err, r) {
        // do something with result
    }
}