mongodb位置操作员错误

Gor*_*Gor 11 arrays updates mongodb

我有这样的对象

{
    "_id" : ObjectId("5742be02289512cf98bf63e3"),
    "name" : "test1",
    "name" : "test1",
    "attributes" : [ 
        {
            "name" : "x",
            "color" : "0xd79c9c",
            "_id" : ObjectId("5742be02289512cf98bf63e8")
        }, 
        {
            "name" : "y",
            "color" : "0xd79c9c",
            "_id" : ObjectId("5742be02289512cf98bf63e7")
        }, 
        {
            "name" : "z",
            "color" : "0xd79c9c",
            "_id" : ObjectId("5742be02289512cf98bf63e6")
        }
    ],
    "__v" : 6
}
Run Code Online (Sandbox Code Playgroud)

我想更新所有文档,并为每个属性设置新字段.所以我想运行单个查询,一次更新所有文档.我想,这个查询会做到这一点

db.spaces.update({}, { $set: { "attributes.0.weight": 2 } }, {multi: true})
Run Code Online (Sandbox Code Playgroud)

但是当我运行此查询时,我收到错误.

"code":16837,
"errmsg":"位置运算符未找到查询所需的匹配.Unexontded update:attributes.$.weight"

所以我不明白为什么.请帮忙

chr*_*dam 21

您需要包含数组字段作为查询文档的一部分才能使用positional operator.

例如,如果您想更新第一个数组元素,{ "attributes.name": "x" }那么您可以遵循以下模式:

db.spaces.update(
   { "attributes.name": "x" }, // <-- the array field must appear as part of the query document.
   { "$set": { "attributes.$.weight": 2 } },
   { "multi": true }
)
Run Code Online (Sandbox Code Playgroud)

对于较新的MongoDB版本3.2.X,您可以使用该updateMany()方法根据上面的过滤器更新集合中的多个文档.

  • db.spaces.update({"attributes.name":{$ exists:true}},{$ set:{"attributes.$.weight":3}},{multi:true})此查询仅更新第一项在数组中 (5认同)
  • @Gor在这种情况下它不起作用的原因是位置`$`运算符充当匹配查询文档的**first**元素的占位符,而不是数组中的所有元素。参考标记重复中的答案以获得解决方案。 (2认同)

Nae*_*ikh 8

位置运算符需要匹配,来自更新查询的匹配部分。

例如:

db.spaces.update({ "attributes.name": "x" }, { $set: { "attributes.0.weight": 2 } }, {multi: true})
Run Code Online (Sandbox Code Playgroud)

这里更新操作的第一个参数将匹配attributes任何元素具有属性的数组name=="x",对于匹配条件的任何元素,位置运算符可用于更新它。

所以,因为name='x',在这种情况下,第一个匹配元素是,

{
            "name" : "x",
            "color" : "0xd79c9c",
            "_id" : ObjectId("5742be02289512cf98bf63e8")
        }, 
Run Code Online (Sandbox Code Playgroud)

它会得到更新。

现在,从您的问题中,我了解到您希望以一种方式更新文档,即在每个文档中您的第一个元素attributeweight=2.

你可以做类似的事情

db.spaces.update({ "attributes.name": { $regex: /^(?=[\S\s]{10,8000})[\S\s]*$/ } }, { $set: { "attributes.0.weight": 2 } }, {multi: true})
Run Code Online (Sandbox Code Playgroud)

我们在这里做的是匹配数组属性中的所有元素。我们使用位置运算符来更新该数组的第一个元素