Maison > Questions et réponses > le corps du texte
描述: 格式如下所示,其中每个对象有_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);
});
});
黄舟2017-04-17 11:12:39
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);
});
});
});
});
阿神2017-04-17 11:12:39
我估计你想要的是 in place update,比如 findAndEval 类似的方法,然后要让你失望了
https://jira.mongodb.org/browse/SERVER-458
目前为止还没有实现,被列在 Planning Bucket B 里,实现目测遥遥无期。
嗯,上面说的没有实现是指没法在服务器端完成(mongo 和 mongod 的关系)
如果在客户端完成,可以用 cursor.forEach 方法,比如
db.students.find().snapshot().forEach(
function (e) {
e.删除score较小的homework!;
db.students.save(e);
}
)