MongoDB:批量更新以插入缺少的部分

时间:2014-08-21 14:06:26

标签: mongodb

我需要通过"默认值"来更新MongoDB中的所有文档。文件:如果"默认值的任何部分"在DB文档中不存在 - 添加此部分,否则不要修改此部分。

我试图通过存储的函数来实现这一点:加载doc,递归更新它,保存它。

insertDefValues.js:

db.system.js.save({_id: "DoInsertDefValues", value: function(data, defValues) 
{
    var modified = false;
    for (var prop in defValues)
    {
        if (data[prop] === undefined)
        {
            data[prop] = defValues[prop];
            modified = true;
        }            
        else if (typeof defValues[prop] === "object")
            modified |= DoInsertDefValues(data[prop], defValues[prop]);
    }
    return modified;
}});

db.system.js.save({_id: "InsertDefValues", value: function() 
{
    var defValues = {
        //...
    };
    var docs = db.collection.find();
    docs.forEach(function(data)
    {
        if (DoInsertDefValues(data, defValues))
            db.collection.save(data);
    });
}});

db.loadServerScripts();
InsertDefValues();

然后我通过mongo shell执行它:

mongo collection insertDefValues.js

问题是这种方法太慢了(测试数据的2K文档上30秒,生产数据库要大得多)。我使用没有批量更新的MongoDB 2.4.10,所以这不是一个选项。我将尝试生成一系列更新,例如:

E.g。对于"默认值":{"1": {"2": "blah"}}

更新

db.collection.update({"1": {$exists: false}}, {$set: {"1": {"2": "blah"}}})
db.collection.update({"1.2": {$exists: false}}, {$set: {"1.2": "blah"}})

还有其他选择吗?

"默认值" doc是7KB紧凑的JSON,没有字符串值。 收集文档的平均大小是10KB的紧凑型JSON。

我可以使用MongoDB-CSharp驱动程序,如果它能产生明显更快的解决方案(我对此表示怀疑)。

2 个答案:

答案 0 :(得分:1)

我在你的代码中发现了一些内容,可能是错误。

InsertDefValues (data, defValues);应为 DoInsertDefValues (data, defValues);,对吧?

保存前不会返回并检查 DoInsertDefValues 中的已修改,这意味着您将保存每个文档,对吗?

脚本在mongo shell - 客户端执行,这可能会降低性能,因为从服务器接收数据并为每个保存操作处理连接套接字的内容。我从mongodb驱动程序中学习了java的这些动作,如果mongo shell与其他驱动程序原理相同,这将是性能低下的主要原因。如果尚未对分片进行分片,则调用db.eval以使脚本在服务器端执行。祝你好运。

答案 1 :(得分:0)

通过生成递归更新解决问题(如问题中所述)。执行时间从30秒降至0.5秒。