如何更新文档中的特定数组?

huangapple go评论88阅读模式
英文:

mgo: how to update a specific array in a document

问题

我在数据库中有这个文档:

[
{
"_id": "53dc97bf91f1f933e15d6fb1",
"attributes": {
"chilled": false,
"flammable": false,
"food": false,
"fragile": false,
"frozen": false,
"hot": false,
"outsized": false
},
"createdAt": "02/08/14 09:48:16",
"customer": "53d68bc091f1f933e15d6f90",
"location": [
{
"count": 0,
"warehouse": "53db430c91f1f933e15d6fa6"
},
{
"count": 34,
"warehouse": "53db430c91g1f933e45d6fa4"
}
],
"name": "test",
"type": "stored",
"updatedAt": ""
}
]

如果我知道仓库的ID,我该如何更新location数组?
这是我现在的代码:

coll := p.GetDb().C("product")
changes := bson.M {
"location": bson.M {
"$elemMatch": bson.M {
"warehouse": bson.ObjectIdHex(warehouseId),
},
},
"$set": bson.M {
"location.$.count": 4,
},
}

err := coll.UpdateId(bson.ObjectIdHex(productId), changes)
if err != nil {
http.Error(res, err.Error(), 500)
return
}

但是出现了这个错误:

在“location.$elemMatch”中,以美元符号($)为前缀的字段“$elemMatch”对于存储无效。

英文:

I have this document inside my database:

[
  {
    "_id": "53dc97bf91f1f933e15d6fb1",
    "attributes": {
      "chilled": false,
      "flammable": false,
      "food": false,
      "fragile": false,
      "frozen": false,
      "hot": false,
      "outsized": false
    },
    "createdAt": "02/08/14 09:48:16",
    "customer": "53d68bc091f1f933e15d6f90",
    "location": [
      {
        "count": 0,
        "warehouse": "53db430c91f1f933e15d6fa6"
      },
      {
        "count": 34,
        "warehouse": "53db430c91g1f933e45d6fa4"
      },
    ],
    "name": "test",
    "type": "stored",
    "updatedAt": ""
  }
]

How can i update the location array if i know the warehouse Id?
This is what i have now

coll := p.GetDb().C("product")
	changes := bson.M {
		"location": bson.M {
			"$elemMatch": bson.M {
				"warehouse": bson.ObjectIdHex(warehouseId),
			},
		},
		"$set": bson.M {
			"location.$.count": 4,
		}, 
	}
	
	err := coll.UpdateId(bson.ObjectIdHex(productId), changes)
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}

But get this error:
> The dollar ($) prefixed field '$elemMatch' in 'location.$elemMatch' is not valid for storage.

答案1

得分: 12

你把顺序写错了。在你的语句中,匹配仓库 "id" 值的部分应该放在 "query" 部分,而不是 "update" 部分。因此,你不需要使用 UpdateId,而是使用 Update,因为它允许更广泛的查询选择:

query := bson.M{
    "_id": bson.ObjectIdHex(productId),
    "location.warehouse": bson.ObjectIdHex(warehouseId)
}

update := bson.M{
    "$set": bson.M{
        "location.$.count": 4
    }
}

err := coll.Update(query, update)

另外,请注意,在这里使用 "点表示法" 是可以的,因为你对数组元素的选择器只是一个单一的字段。只有当数组中有多个字段需要进行匹配时,才需要使用 $elemMatch

英文:

You wrote this the wrong way around. The match on the warehouse "id" value belongs in the "query" portion of your statement and not in the "update" section. As such, you don't want the UpdateId variant, but the Update as it allows a wider query selection:

query := bson.M{
    "_id": bson.ObjectIdHex(productId),
    "location.warehouse": bson.ObjectIdHex(warehouseId)
}

update := bson.M{
    "$set": bson.M{
        "location.$.count": 4
    }
}

err := coll.Update(query,update)

Also note that the the "dot notation" form is fine here as your selector for the array element is just a singular field. You typically only need $elemMatch when there is more that one field in the array to establish the match.

huangapple
  • 本文由 发表于 2014年8月2日 17:41:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/25093667.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定