描述: 格式如下所示,其中每个对象有_id,name,和一个数组scores,其中可以看到修改前的数组中,每个document有两个type为"homework"的对象。
*提问*: 问题是如何操纵mongo数据库,批量修改db.students,让每个document中,删除score较小的homework,而保留score较大的homework。
修改前:
{ "_id" : 100, "name" : "Demarcus Audette", "scores" : [ { "score" : 47.42608580155614, "type" : "exam" }, { "score" : 44.83416623719906, "type" : "quiz" }, { "score" : 19.01726616178844, "type" : "homework" }, { "score" : 39.01726616178844, "type" : "homework" } ]}
修改后:
{ "_id" : 100, "name" : "Demarcus Audette", "scores" : [ { "score" : 47.42608580155614, "type" : "exam" }, { "score" : 44.83416623719906, "type" : "quiz" }, { "score" : 39.01726616178844, "type" : "homework" } ]}
下面附上一段nodejs上跑的代码(自己写的,有问题跑不通,作为参考):
var MongoClient = require('mongodb').MongoClient;MongoClient.connect('mongodb://localhost:27017/school', function(err, db){ if(err) throw err; var query = {}; var cursor = db.collection('students').find(query); cursor.each(function(err, doc){ if(err)throw err; if(doc == null){return db.close();} /*TODO*/ var target1 = doc.scores[2]; var target2 = doc.scores[3]; if(target1 < target2) doc.update({$unset: target1}); else doc.update({$unset: target2}); console.dir("Successfully found " + target1); });});
解决方案
var MongoClient = require('mongodb').MongoClient;MongoClient.connect('mongodb://school:school@localhost:27017/school', function(err, db) { if (err) { throw err; } var student = db.collection('students'); var updateData = function(newdoc) { //把旧的删除 student.findAndRemove({_id: newdoc._id}, function(err, olddoc) { if (err) { throw err; } olddoc && console.log('remove olddoc id: %s', olddoc._id); //插入新的 student.insert(newdoc, function(err, saveResult) { if (err) { throw err; } saveResult && console.log('[OK] update ok , id: %s', newdoc._id); saveResult || console.log('[ERR] update fail, id: %s', newdoc._id); }); }); }; //插入测试数据 student.insert([ { name: 'hehehe', scores: [ { score: 97.42608580155614, type: 'exam', }, { score: 14.83416623719906, type: 'quiz', }, { score: 55.01726616178844, type: 'homework', }, { score: 3.0172661617884, type: 'homework', } ], }, { name: 'Demarcus Audette', scores: [ { score: 47.42608580155614, type: 'exam', }, { score: 44.83416623719906, type: 'quiz', }, { score: 19.01726616178844, type: 'homework', }, { score: 39.0172661617884, type: 'homework', } ], }, ], function(err, result) { if (err) { throw err; } //聚合 student.aggregate([ {$unwind: '$scores'}, {$group: { '_id': { '_id': '$_id', name: '$name', type: '$scores.type', }, score: { '$max': '$scores.score' } }}, {$project: { '_id': { _id: '$_id._id', name: '$_id.name', }, scores: { type: '$_id.type', score: '$score', }, }}, {$group: { '_id': '$_id', scores: { '$push': '$scores', } }} ], function(err, result) { if (err) { throw err; } //循环结果 result.forEach(function(item) { item = { _id: item._id._id, name: item._id.name, score: item.scores }; updateData(item); }); }); });});