【问题标题】:How could I run this as one command in Mongo Shell我如何在 Mongo Shell 中将其作为一个命令运行
【发布时间】:2014-08-21 08:52:53
【问题描述】:
db.people.update(
    { "age": "Thirty Two" }, { age: 32 }, { upsert: false }
)

db.people.update(
    { "age": "Fifty-Five" }, { age: 55 }, { upsert: false }
)

db.people.update(
    { "age": "Twenty" }, { age: 20 }, { upsert: false }
)

我在想:

db.people.update(
    [{ "age": "Thirty Two" }, { age: 32 }, { upsert: false }],
    [{ "age": "Fifty-Five" }, { age: 55 }, { upsert: false }],
    [{ "age": "Twenty" }, { age: 20 }, { upsert: false }]
)

但这不起作用..我知道我真的很累,想不起来......

【问题讨论】:

  • 您要使用$set 还是multi=true?您拥有的更新将最多替换一个匹配的文档,并将其完全替换为更新文档。我猜一个人不仅仅是{ "age" : 32 },还有不止一个人32岁。
  • 你好 wd!我不知道,我是mongo的新手。您可以向我解释更多的任何可能性。我只是想弄清楚如何一次完成所有工作。 $set 和 multi=true 的其他选项是什么?

标签: javascript mongodb arguments updatemodel


【解决方案1】:

为了详细说明我的评论并提出db.eval() 的替代方案,“无操作员”更新将整个匹配的文档替换为更新文档(保留_id 除外):

> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 32 }
{ "_id" : 1, "name" : "Sam Small", "age" : 26 }
{ "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
> db.people.update({ "age" : 32 }, { "age" : 45 })
> db.people.find()
{ "_id" : 0, "age" : 45 }
{ "_id" : 1, "name" : "Sam Small", "age" : 26 }
{ "_id" : 2, "name" : "Mindy Medium", "age" : 26 }

只更改一个字段意味着使用update operator,例如$set

> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 32 }
{ "_id" : 1, "name" : "Sam Small", "age" : 26 }
{ "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
> db.people.update({ "age" : 32 }, { "$set" : { "age" : 45 } })
> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 45 }
{ "_id" : 1, "name" : "Sam Small", "age" : 26 }
{ "_id" : 2, "name" : "Mindy Medium", "age" : 26 }

默认情况下,更新只影响一个匹配的文档。选项multi=true 将导致更新影响所有匹配的文档:

> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 32 }
{ "_id" : 1, "name" : "Larry Large", "age" : 32 }
{ "_id" : 2, "name" : "Sam Small", "age" : 26 }
{ "_id" : 3, "name" : "Mindy Medium", "age" : 26 }
> db.people.update({ "age" : 32 }, { "$set" : { "age" : 45 } })
> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 45 }
{ "_id" : 1, "name" : "Larry Large", "age" : 32 }
{ "_id" : 2, "name" : "Sam Small", "age" : 26 }
{ "_id" : 3, "name" : "Mindy Medium", "age" : 26 }
> db.people.update({ "age" : 26 }, { "$set" : { "age" : 23 } }, { "multi" : true })
> db.people.find()
{ "_id" : 0, "name" : "Barney Big", "age" : 45 }
{ "_id" : 1, "name" : "Larry Large", "age" : 32 }
{ "_id" : 2, "name" : "Sam Small", "age" : 23 }
{ "_id" : 3, "name" : "Mindy Medium", "age" : 23 }

因此,要在 shell 中执行您在问题中询问的更新,我会使用 for 循环,但无需使用 db.eval,而是支持多次调用 db.people.update()

> updates = [
    [{ "age": "Thirty Two" }, { "$set" : { "age" : 32 } }],
    [{ "age": "Fifty-Five" }, { "$set" : { "age" : 55 } }],
    [{ "age": "Twenty" }, { "$set" : { "age" : 20 } }]
]
> updates.forEach(function(pair) {
    db.people.update(pair[0], pair[1])
})

如果您有数百个更新并且正在使用 MongoDB 2.6 或更高版本,请查看bulk operationsdb.collection.update() docs有更多信息。

【讨论】:

  • 抱歉,我花了这么长时间,才回到这个项目。感谢我将您标记为最有帮助的答案!
【解决方案2】:

也许这就是你想要的。

db.eval(function(name, options) {
    var coll = db.getCollection(name);
    for (var x in options) {
        var option = options[x];
        coll.update(option[0], option[1], option[2]);
    }
},
"people",
[
    [{ "age": "Thirty Two" }, { age: 32 }, { upsert: false }],
    [{ "age": "Fifty-Five" }, { age: 55 }, { upsert: false }],
    [{ "age": "Twenty" }, { age: 20 }, { upsert: false }]
]);

【讨论】:

  • 当我是一组数组括号,呵呵。哦,我喜欢 eval 函数和循环谢谢!
  • 请不要使用db.eval()。服务器端 javascript 存在很多问题,包括速度慢、安全漏洞以及与分片集合不兼容。查看更多in the docs
  • @wdberkeley:我看到了db.eval() 的局限性。但有时它可能是解决 V2.6 之前特定问题的唯一方法。例如,有数千个文档要批量修改。如果一个一个更新,可能需要一分钟。使用db.eval() 时大约 2 秒就足够了。无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
  • 1970-01-01
  • 2018-05-16
  • 2022-10-13
  • 1970-01-01
  • 2011-07-05
相关资源
最近更新 更多