mgo: how to update a specific array in a document

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.

Upvotes: 4

Views: 6948

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151122

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.

Upvotes: 13

Related Questions