Hello,
I create a collection with the _id in string, normally the _id is 3 characters. When I search the doc by _id, by the function FindOne, I can always get result. But we I find and update a doc by the function FindOneAndUpdate, with the same ID, I will get error message “an ObjectID string must be exactly 12 bytes long (got 3)”. The update operation is just to change a counter of the doc, and I am sure that the counter has been changed successfully, as I can check the changes happened from compass. So the things looks weird, the value changed successfully but db return an error.
The version of my database v3.6.17.
Can anyone give some hint to fix the problem?
Regards,
James
Hi,
Can you give us a code sample to work with? Three characters is not a valid ObjectID, so my guess is that the update is executing successfully, but you’re decoding the result into a struct where the field type is primitive.ObjectID
, which fails. A code sample would help to figure out the root cause, though.
– Divjot
Hello Divjot, nice to meet you again. I hope you are doing well and are safe.
//The code here is the API that will access db by id in string
func FindAndUpdateDocByStringID(coll *mongo.Collection, id string, update bson.M, result interface{}) error {
prefix := coll.Name()
err := coll.FindOneAndUpdate(context.TODO(), bson.D{{Key: "_id", Value: id}}, update).Decode(result)
if err != nil {
if strings.Contains(err.Error(), NoDocument) {
return errors.NotFound(prefix+"_not_found", err.Error())
}
return errors.InternalServerError(prefix+"_internal_error", err.Error())
}
return nil
}
//The code here is the calling of the API
update := bson.M{"$inc": bson.M{"nbr_details_views": 1}}
modelPlace := Place{}
err := dboperate.FindAndUpdateDocByStringID(collection, in.Value, update, &modelPlace)
//The code here is the definition of the Place
type Place struct {
// Id of the Place
ID string `json:"id,omitempty" bson:"_id,omitempty"`
// UserID of the owner of the Place
UserID primitive.ObjectID `json:"user_id,omitempty" bson:"user_id,omitempty"`
// City of the Place
City string `json:"city,omitempty" bson:"city,omitempty"`
// Description of the Place (long text)
Description string `json:"description,omitempty" bson:"description,omitempty"`
// Photos lists the available photos URL
Photos []string `json:"photos,omitempty" bson:"photos,omitempty"`
// Nbr of views on detail this place
NbrDetailsViews int32 `json:"nbr_details_views,omitempty" bson:"nbr_details_views,omitempty"`
}
This error comes from the part of the code that tries to decode strings as ObjectIDs, so my guess is that it’s coming from the Decode
call when decoding the UserID
field as that’s the only field in the Place
struct of type primitive.ObjectID
. If you can easily reproduce this, it would be really helpful if you could replace the Decode
call with DecodeBytes
and print the result. That will return a bson.Raw
that shows the exact document being returned by the server and can show us which field is causing the error.
– Divjot
1 Like