i mongodb beginner , working on homework problem, dataset looks this
{ "_id" : { "$oid" : "50906d7fa3c412bb040eb577" }, "student_id" : 0, "type" : "exam", "score" : 54.6535436362647 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb578" }, "student_id" : 0, "type" : "quiz", "score" : 31.95004496742112 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb579" }, "student_id" : 0, "type" : "homework", "score" : 14.8504576811645 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb57a" }, "student_id" : 0, "type" : "homework", "score" : 63.98402553675503 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb57b" }, "student_id" : 1, "type" : "exam", "score" : 74.20010837299897 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb57c" }, "student_id" : 1, "type" : "quiz", "score" : 96.76851542258362 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb57d" }, "student_id" : 1, "type" : "homework", "score" : 21.33260810416115 } { "_id" : { "$oid" : "50906d7fa3c412bb040eb57e" }, "student_id" : 1, "type" : "homework", "score" : 44.31667452616328 } as part of problem have delete each student, 'homework' document lowest score. here strategy
in aggregate pipeline
1: first filter documents type:homeworks
2: sort student_id, score
3: group on student_id, find first element
this give me documents lowest score,
however how delete these elements original dataset? guidance or hint?
use cursor result aggregation loop through documents cursor's foreach() method , remove each document collection using _id query in remove() method. this:
var cursor = db.grades.aggregate(pipeline); cursor.foreach(function (doc){ db.grades.remove({"_id": doc._id}); }); another approach create array of document's _ids using map() method , remove documents like:
var cursor = db.grades.aggregate(pipeline), ids = cursor.map(function (doc) { return doc._id; }); db.grades.remove({"_id": { "$in": ids }}); -- update --
for large deletion operations, may more efficient copy documents want keep new collection , use drop() on original collection. copy essential documents aggregation pipeline needs return documents without lowest homework doc , copy them collection using $out operator final pipeline stage. consider following aggregation pipeline:
db.grades.aggregate([ { '$group':{ '_id': { "student_id": "$student_id", "type": "$type" }, 'lowest_score': { "$min": '$score'}, 'data': { '$push': '$$root' } } }, { "$unwind": "$data" }, { "$project": { "_id": "$data._id", "student_id" : "$data.student_id", "type" : "$data.type", "score" : "$data.score", 'lowest_score': 1, "ishomeworklowest": { "$cond": [ { "$and": [ { "$eq": [ "$_id.type", "homework" ] }, { "$eq": [ "$data.score", "$lowest_score" ] } ] }, true, false ] } } }, { "$match": {"ishomeworklowest" : false} }, { "$project": { "student_id": 1, "type": 1, "score": 1 } }, { "$out": "new_grades" } ]) in can drop old collection db.grades.drop() , query on db.new_grades.find()
Comments
Post a Comment