2

I have this data schema:

"person": { "name": "Neeraj", "hobbies": ["movies" ] }

This is the struct to insert the document in MongoDB

type Person struct {
  Id   primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
  Name string `bson:"name,omitempty" json:"name,omitempty"`
  Hobbies []string `json:"hobbies,omitempty" bson:"hobbies,omitempty"`
}

When PUT person API is called without the hobbies field, I would expect it to not update the hobbies field in DB. In this case when I parse the body, the struct has Hobbies set as null and because of 'omitempty' bson tag, it does not update the hobbies field in DB, which is fine.

filter := bson.D{{"_id", oid}}
update := bson.M{
    "$set": record,
}
result, err := collection.UpdateOne(ctx, filter, update)

However, when PUT person API is called with the hobbies field set to an empty array, I would expect it to update the hobbies field and set it to empty. But in this case too, the record struct has hobbies field set to null, and it doesn't update the hobbies field.

How do I do this in go, so that my code caters to all of following update payload? I am using golang official mongo driver.

{
   "name": "john"  // Should not modify the hobbies field.
}

{
  "name": "john",
  "hobbies": []  // // Should update the hobbies field to an empty array
}
1
  • I got some help and was able to fix this by using *[]string type instead of []string for hobbies. Commented Jun 6, 2021 at 5:47

1 Answer 1

-1

It sounds like you want to merge the person object based on what was provided in the request, whereas the MongoDB $set operator, "replaces the value of a field with the specified value." Because MongoDB doesn't understand how complex types should be merged, you'll have to specify the exact merging logic yourself.

filter := bson.M{"_id": oid}
set := bson.M{
    "name": record.Name,
}
if (record.Hobbies) != nil {
    set["hobbies"] = record.Hobbies
}
update := bson.M{"$set": set}
Sign up to request clarification or add additional context in comments.

2 Comments

I tried following, but it did not help. when I pass the empty array, it does not clear out the existing values. update := bson.M{ // "$set": record, "$set": bson.M{ "name": record.Name, }, "$addToSet": bson.M{"hobbies": bson.M{"$each": record.hobbies}}, } result, err := rc.collection.UpdateOne(ctx, filter, update)...What I need is a way to know if the API is called with no hobbies or an empty array (Should I check the json structure manually?) and then write a generic code for DB update which works for both nil and empty array
Ah, I apologize I mis-understood, I updated my answer. Yes you'll have to check the structure manually and update your query accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.