4

I'm creating a simple todo rest API using golang and mongodb. I'm also using the mongo-go-driver library.

Basically, I managed to upload my data to mongodb and I'm able to retrieve the information, but I encounter some problems when I try to use the findOneAndUpdate function. I'm able to update my data using findOneAndReplace, However, I want to update the information using a struct and the findOneAndUpdate function

Here is my struct:

type Todo struct {
   ObjectId string
   ID       string `json:"ID,omitempty"`
   Title    string `json:"Title,omitempty" bson:"Title"`
   Category string `json:"Category,omitempty" bson:"Category"`
   Content  string `json:"Content,omitempty" bson:"Content"`
   Created  string `json:"Creation_time,omitempty" bson:"Creation_time"`
   Modified string `json:"Modification_time,omitempty" bson:"Modification_time"`
   State    string `json:"State,omitempty" bson:"State"`

}

Here is the function that decodes my request body into a struct:

func UpdateTodo (w http.ResponseWriter, r *http.Request){
var todo models.Todo
_ = json.NewDecoder(r.Body).Decode(&todo)
urlTodoId := chi.URLParam(r, "id")
UpdateTodoById(todo, urlTodoId)

}

And finally here is the function that updates the data:

func UpdateTodoById(todo m.Todo, todoId string) interface{}{

var todoUpdated m.Todo

objId, err := objectid.FromHex(todoId)
helpers.PanicErr(err)
filter := bson.NewDocument(bson.EC.ObjectID("_id", objId))
fmt.Println(filter)

err = db.Collection(COLLNAME).FindOneAndUpdate(context.Background(), filter, todo).Decode(&todoUpdated)
fmt.Println(todoUpdated)
helpers.PanicErr(err)

return  todoUpdated}

When I send the request I receive an error: update document must contain key beginning with '$

So can anyone help? Is there a way to solve this? and use a struct to update the data find the function findOneAndUpdate? Or is this driver not developed enough to do that yet?

Thank you.

Community
  • 1
  • 1
Marius
  • 537
  • 1
  • 6
  • 23
  • 1
    Also related / possible duplicate: [mongodb-go-driver/bson struct to bson.Document encoding](https://stackoverflow.com/questions/53110020/mongodb-go-driver-bson-struct-to-bson-document-encoding/53157611#53157611). – icza Nov 14 '18 at 10:29
  • You want [`FindOneAndReplace()`](https://godoc.org/github.com/mongodb/mongo-go-driver/mongo#Collection.FindOneAndReplace) if your intention is to "replace" the matched document. This is now "hardened" in all API across all drivers where the two methods work differently. The "Update" varieties use [atomic operators](https://docs.mongodb.com/manual/reference/operator/update/) as mandatory. – Neil Lunn Nov 14 '18 at 10:30
  • @icza That would possibly be the next error thrown. But `update document must contain key beginning with '$` is pretty specific. – Neil Lunn Nov 14 '18 at 10:30
  • @NeilLunn Yes, I just wanted to give a heads-up where to go from there (when he corrects to use `$set`). – icza Nov 14 '18 at 10:32
  • @icza So you're suggesting me to make a helper function which would convert my struct into a bson document and then try it using this: `bson.NewDocument(bson.EC.SubDocument("$set", doc))` ? – Marius Nov 14 '18 at 10:48
  • @Marius If you want to update just some fields, prepared as a struct value. This also requires you to specify the `,omitempty` option in the `bson` tags. If you want to replace the complete document, `FindAndReplace()` might be a better option as Neil suggested. – icza Nov 14 '18 at 10:52
  • @icza, Thank you for your help, I created the converter to bson function and now everything works exactly as i wanted to! – Marius Nov 14 '18 at 11:34

0 Answers0