3

I am facing a issue with update document using golang mongo driver. Scenario: I want to update a field that is nested in a struct. For ex: StructOuter -> structInner -> field1, field2, field3. Now if I want to update the field3 and I have the corresponding value as another struct, how can i go ahead by just updating this field alone. I tried with code below but it updates the whole structInner leaving only field3:

conv, _ := bson.Marshal(prod)
bson.Unmarshal(conv, &updateFields)
update := bson.M{
   "$set": updateFields,
}
model.SetUpdate(update). 

Sample JSON:

{
    "field_one": "value",
    "data": {
        "field_two": [
            "data1",
            "data2"
        ],
        "field_three": "check",
        "field_four": "abc",
        "field_five": "work",
    }
}

I want to avoid hard coded field query for updating.

Just want to know if this is supported, if yes can you help me with it and also point to some deep dive links on this.

2
  • Can you please add a sample json to explain the structure of document you want to update Commented Apr 29, 2020 at 10:39
  • Added the sample JSON Commented Apr 29, 2020 at 12:20

1 Answer 1

2

If you have control over the code, you could try creating methods on the struct. These methods can help you construct the fields path to perform partial update. For example, if you have the following structs:

type Outer struct {
    Data Inner  `bson:"data"`
}

type Inner struct {
    FieldThree string `bson:"field_three"`
    FieldFour string `bson:"field_four"`
}

You can try adding methods as below to construct update statements. These are returned in the dot-notation format.

func (o *Outer) SetFieldThree(value string) bson.E {
    return bson.E{"data.field_three", value}
}
func (o *Outer) SetFieldFour(value string) bson.E {
    return bson.E{"data.field_four", value}
} 

To update, you can construct the statements like below:

x := Outer{}
var updateFields bson.D
updateFields = append(updateFields, x.SetFieldThree("updated"))
updateFields = append(updateFields, x.SetFieldFour("updated"))

statement := bson.D{{"$set", updateFields}} 
result, err := collection.UpdateOne(ctx, bson.M{}, statement)
Sign up to request clarification or add additional context in comments.

1 Comment

Got it solved by generating single level map from nested map link

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.