Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 317
Anthony De Meulemeester Avatar asked Dec 19 '22 12:12

Anthony De Meulemeester


1 Answers

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.

like image 114
Neil Lunn Avatar answered Jan 09 '23 21:01

Neil Lunn