I've modeled a has-many relationship in MongoDB with a Group that has an array of Students as one of the fields.
When a Student is deleted, I want to go through all the Groups, and for each Group that has the deleted_student in its Group.Students, remove the deleted_student from the array.
To remove the deleted_student from the array, I have a helper function, RemoveItem that I'd liek to use.
What's the "Mongo" way of apply this function to all the records in a collection? Or should I just return all the Groups, then iterate through each and perform the operation on the field. Something like this (in Go using the mgo library)
groups := conn.C("groups")
allGroups := groups.Find()
for _, group := range allGroups {
group.Students = RemoveItem(id, group.Students)
}
// Helper function that removes a mgo.DBRef from an array of mgo.DBRefs based on ID string
func RemoveItem(objectId string, array []mgo.DBRef) []mgo.DBRef {
updatedArray := []mgo.DBRef{}
for _, item := range array {
if item.Id != objectId {
updatedArray = append(updatedArray, item)
}
}
return updatedArray
}
I believe it is still not possible to do a single operation to update select elements within an array based on criteria. However, you can limit your results a bit before beginning your iteration.
groupsToBeUpdated := groups.Find(bson.M{"students": bson.M{"$elemMatch": bson.M{"deleted_student": true}}})
From here you can iterate through, however I would inject your db resource into the RemoveItem method so that it can make the update there. This allows you to concurrently update the documents. See my gist here for a worker example: https://gist.github.com/KyleWolfe/7c54018a9ed16517c0dd or on playground: http://play.golang.org/p/njtAALaH1t
Edit: Additionally, if you had an interface set up that also held your db resource, you could then have a method of RemoveStudents(). Everything that method would need would be accessible though your Group struct.