Hello I’m using golang and mongodb but I have a problem when updating a collection, I have a collection called site which is a struct in Go, inside this one I have other collection called shop which has also 2 more embedded collections (as you can see below).
type Site struct { ID bson.ObjectIdbson:"_id"Owner bson.ObjectIdbson:"owner"Domain stringbson:"domain"//... more fields Shop *Shopbson:“shop"} // Shop holds site's information about a user's shop type Shop struct { ID bson.ObjectIdjson:“id” bson:”_id"Title stringjson:“title” bson:"title"Description stringjson:“description” bson:"description"Categories []*Categoryjson:“categories” bson:"categories"Products []*Productjson:“products” bson:“products”} // Categories and products collection omited for brevity
I have used the update method and it creates a category inside the categories array but when I try to insert a new category it just updates the previous category, I have tried to use the create method but it tries to create a complete new site and sends me an error about duplicating the ObjectId.
At the beginning the property shop is null in the db so when I try to create a category I have to create the shop first to put in there the category but how to get the previous categories when a user tries to insert a second category?. I’m confused and I hope you can understand me, thanks.
It will be helpful, and you’ll get more specific advice if you could include all of your code that is calling the DB. Also if you enclose your code here on the forum with three backticks " ` " it will format it for easier reading.
Thanks for the advice, I could solve my problem by checking if the shop struct is empty create one and then insert the categories. But I think my code is awful I have to refactor it and make it better maybe I can ask for some tips
Definitely, but it’s hard to know what your code is actually doing without seeing it first hand. I mean from the bit of information you included about the behavior of your create function, it sounds like you are inserting static data for the ObjectId and it won’t ever change, but I have no way of knowing without seeing the code.
Don’t be embarrassed to share your code as we are all here to help each other.
func CategoriesStore(res http.ResponseWriter, req *http.Request, p httprouter.Params) {
//get session data account
_, err := models.GetSession(req)
//if not an authenticated user, redirect to the login site
if err != nil {
http.Redirect(res, req, "/login", http.StatusSeeOther)
return
}
idSite := bson.ObjectIdHex(p.ByName("uid"))
s, err := models.GetSiteByID(idSite)
if err != nil {
utils.ToJSON(res, map[string]string{"error": "Error" + err.Error()}, http.StatusInternalServerError)
return
}
c := &models.Category{}
if err := json.NewDecoder(req.Body).Decode(c); err != nil {
utils.ToJSON(res, map[string]string{"error": "Error" + err.Error()}, http.StatusInternalServerError)
return
}
c.ID = bson.NewObjectId()
sp := &models.Shop{}
if s.Shop == nil {
sp = &models.Shop{ID: bson.NewObjectId()}
} else {
sp = s.Shop
}
if sp.Categories == nil {
sp.Categories = append(sp.Categories, c)
} else {
s.Shop.Categories = append(s.Shop.Categories, c)
}
s.Shop = sp
if err := s.UpdateSite(); err != nil {
utils.ToJSON(res, map[string]string{"error": "Error" + err.Error()}, http.StatusInternalServerError)
return
}
utils.ToJSON(res, map[string]string{"message": utils.BackendTranslate("success-save")}, http.StatusOK)
}
That is my function as I said before I check if the s.Shop is nil if so I create a new one with a specific ObjectId otherwise I use the s.Shop already saved and I apply the same process to the sp.Categories field and finally I call the UpdateSite method (which you can ckeck below) and save the category.
func (s *Site) UpdateSite() (err error) {
dbsess, err := configuration.GetConnection()
if err != nil {
fmt.Println("Error Connecting to the DB")
return
}
defer dbsess.Close()
dbsess.SetSafe(&mgo.Safe{})
c := dbsess.DB(d.Databases["db_sites"]).C("sites")
query := bson.M{"_id": s.ID}
change := bson.M{"$set": s}
err = c.Update(query, change)
if err != nil {
fmt.Println("(site.Update): Error trying to update Site - ", err)
return
}
return
}
I might be wrong, but I think the problem is that your struct has a slice of Category struct pointers, and same for products. When what you are wanting is different data to insert to the database on update. You are passing pointed to data and that would explain the same objectId? Correct me if I’m wrong but that looks like the problem to me.