I am creating an application, and it has a function which removes elements from an array inside a document in a MongoDB collection.
I need a way to unset the array's field as soon as the array becomes empty right after a remove operation. I need to do this so that I can differentiate between a document that has a non-empty array, and a document that has an empty array.
For example, right now my section
collection looks like:
db.section.find({})
{ "_id" : ObjectId("57a0a38ad1c6ef24376477c5"), "sectionid" : "BTE4B",
"sectionname" : "BTech 4B", "year" : 4,
"session" : 2016, "courseid" : "BTE-CS", "password" : "pm8xTE0-",
"students" : 35, "addedon" : "2016-08-02 19:13:38", "teachers" : [ ] }
{ "_id" : ObjectId("57a0a96bd1c6ef24376477cd"), "sectionid" : "BTE4D",
"sectionname" : "BTech 4D", "year" : 4, "session" : 2016, "courseid" :
"BTE-CS", "password" : "sHhKr0Ov", "students" : 41, "addedon" :
"2016-08-02 19:38:43", "teachers" : [ { "facultyid" : "CS-102",
"subjectid" : "CS-ALGO" } ] }
I had applied a $pull operation using mgo on the teachers
array of the first document, but I need a way to $unset
it when it becomes empty.
Currently, I have managed to create a workaround in Go, but I would like to get away without any workarounds.
I hope I am not missing something very trivial here.
Thanks!
Would suggest using the findAndModify()
API to do the $pull
update operation first, this will return the modified document which you can then access the teachers array for checking. Once you check for array emptiness, you can then issue another update operation that calls the $unset
operator on the teachers field if the array key has zero elements.
A canonical example in mongo shell follows:
change = db.section.findAndModify({
query: { "sectionid": "BTE4D", "teachers.facultyid": "CS-102" },
update: { "$pull": { "teachers": { "facultyid" : "CS-102" } } },
new: true
});
printjson(change);
if (!change.teachers[0]) {
db.section.update(
{ "_id": change._id },
{ "$unset": { "teachers": "" } }
);
}
db.section.find({ "_id": change._id })
Implementing this with mgo, you would need the Query.Apply
method which essentially wraps the findAndModify
MongoDB command
change := mgo.Change{
Update: bson.M{"$pull": bson.M{"teachers": bson.M{"facultyid": "CS-102"}}},
ReturnNew: true,
}
info, err = col.Find(M{"sectionid": "BTE4D"}).Apply(change, &doc)
fmt.Println(doc.N)
To differentiate empty arrays from non-empty you can use the find command with the $size operator.
If you choose to remove empty arrays you can issue $pull operator with MongoDB findAndModify (refer the mgo documentation for more details) which can atomically return modified document, check if the array is empty and unset it with another query.