我正在尝试更新MongoDB中的嵌套文档,该文档看起来类似于下面的内容(缩写为简洁)。
{
"cols": "20",
"saveTime": "2014-06-15-10:44:09",
"rows": "20",
"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8",
"players": [
{
"id": "Inhuman",
"num": "1",
"color": "00ff00ff",
"name": "badComputer",
"type": "1"
},
<...>
],
"nodes": [
{
"g": "1",
"c": "0",
"r": "0",
"a": "0",
"o": ""
},
{
"g": "1",
"c": "0",
"r": "1",
"a": "0",
"o": ""
}
<...>
],
}
我要做的是更新其中一个节点。例如,我想更改节点:
{ "g": "1", "c": "0", "r": "0", "a": "0", "o": ""}
到
{ "g": "1", "c": "0", "r": "0", "a": "5", "o": ""}
我尝试使用点(。)表示法,使用$ set命令,ala:
db.game.update({"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8"}, { $set: {"nodes.r":"0", "nodes.c":"0", "nodes.a":"5"}}),
但这并没有给我预期的行为,因为我正在使用相同的r和c值更新所有节点。这显然不是我想要的,但我不知道如何更新本文档的特定部分。有谁知道如何做到这一点?
答案 0 :(得分:1)
如果您要更新&#34;节点&#34;中的特定项目数组,你不知道的位置,但你知道&#34;标准&#34;要匹配该项,那么您需要$elemMatch
运算符以及更新方中的positional $
运算符:
db.game.update(
{
"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8",
"nodes": { "$elemMatch": { "g": 1, "r": 0 } }
},
{ "$set": { "nodes.$.c":"0", "nodes.$.a":"5" } }
)
positional $
运算符包含匹配的&#34;索引&#34;第一个元素的位置&#34;匹配&#34;根据您的查询条件。如果您不使用$elemMatch
并使用&#34;点符号&#34;相反,然后匹配仅对包含值为真的整个文档有效,并且不反映&#34;位置&#34;匹配两个字段条件的元素。
必须注意这是第一个&#34;匹配,通常预期为唯一匹配。原因是位置操作符只包含&#34;第一个&#34;有多个匹配的位置。要以这种方式更新多个符合条件的数组项,则需要多次发出更新,直到文档不再被修改。
对于一个已知的&#34;你可以随时直接使用&#34;点符号&#34;表单,包括您要更新的元素的位置:
db.game.update(
{
"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8",
},
{ "$set": { "nodes.0.c":"0", "nodes.0.a":"5" } }
)
因此第一个元素的索引位置为0
,第二个元素的索引位置为1
,依此类推。
注意在这两种情况下,您只需要传递到$set
您想要更改的字段。因此,除非您不确定存在的值(如果这是您的查询,情况就不是这样),那么您不需要设置&#34;字段到它们已经包含的值。
答案 1 :(得分:0)
要更新特定节点 - 您需要将其放在搜索的查询部分。
在
中 db.game.update({"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8","nodes.r":"0",
"nodes.c":"0", "nodes.a":"5" }, { $set: {"nodes.$.r":"0", "nodes.$.c":"0", "nodes.$.a":"5"}})
您会看到$ sign将其找到的节点对象与呼叫的第一部分(查询)匹配,并将您发送到呼叫的第二部分(投影)部分。 另外check out this question