検索

ホームページ  >  に質問  >  本文

node.js - mongodb高级修改问题

描述: 格式如下所示,其中每个对象有_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);
    });
});
PHPzPHPz2786日前561

全員に返信(2)返信します

  • 黄舟

    黄舟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);
          });
        });    
    
      });
    
    
    });
    

    返事
    0
  • 阿神

    阿神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);
      }
    )
    

    返事
    0
  • キャンセル返事