将新字段添加到嵌套数组中的所有文档

Mic*_*son 9 mongodb

我有一个人员文件数据库.每个都有一个名为photos的字段,这是一组照片文档.我想为每个照片文档添加一个新的"已审核"标志,并将其初始化为false.

这是我尝试使用的查询:

db.person.update({ "_id" : { $exists : true } }, {$set : {photos.reviewed : false} }, false, true)
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

SyntaxError: missing : after property id (shell):1
Run Code Online (Sandbox Code Playgroud)

这是可能的,如果是的话,我在更新中做错了什么?

以下是"人"文档的完整示例:

{
"_class" : "com.foo.Person",
"_id" : "2894",
"name" : "Pixel Spacebag",
"photos" : [
    {
        "_id" : null,
        "thumbUrl" : "http://site.com/a_s.jpg",
        "fullUrl" : "http://site.com/a.jpg"
    },
    {
        "_id" : null,
        "thumbUrl" : "http://site.com/b_s.jpg",
        "fullUrl" : "http://site.com/b.jpg"
    }]
}
Run Code Online (Sandbox Code Playgroud)

任何能告诉我更清洁的人为什么不使用查询更新"所有文件"的奖励业力 { "_id" : { $exists : true } }

Gat*_* VP 8

这是可能的,如果是的话,我在更新中做错了什么?

不可以.一般来说,MongoDB只擅长对顶级对象进行更新.

这里的例外是$ position运算符.来自文档:Use this to find an array member and then manipulate it.

但是,在您的情况下,您想要修改数组中的所有成员.这不是你需要的.

任何能告诉我清洁工为什么更新"所有文件"的人的业力奖励

试试db.coll.update(query, update, false, true),这将发出"多"更新.最后一个true是什么使它成为一个多.

这可能吗,

你有两个选择:

  1. 编写for循环以执行更新.它基本上是一个嵌套for循环,一个循环遍历数据,另一个循环遍历子数组.如果你有很多数据,你会想要写这是你选择的驱动程序(可能还有多线程).
  2. 编写代码以处理reviewed为可空的.写入数据,如果它遇到reviewed未定义的照片,那么它必须是false.然后,您可以适当地设置字段并将其提交回DB.

方法#2是你应该习惯的东西.随着数据的增长和添加字段,很难"反向移植"所有旧数据.这类似于在DB中有1B项时在SQL中发出架构更改的问题.

相反,只需使您的代码抵制null并学会将其视为默认值.

但是,这仍然不是您寻求的解决方案.


zst*_*ate 7

对于仍在寻找答案的用户,可以使用带有所有位置运算符的MongoDB 3.6来$[]查看文档

db.getCollection('person').update(
   {},
   { $set: { "photos.$[].reviewed" : false } },
   { multi: true}
)
Run Code Online (Sandbox Code Playgroud)