无法从MongoDB中的文档数组中删除最低分

时间:2013-10-29 00:09:29

标签: java mongodb

这是我的收藏品的样子:

db.students.find({_id:100}).pretty()
{
    "_id" : 100,
    "name" : "Demarcus Audette",
    "scores" : [
        {
            "type" : "exam",
            "score" : 30.61740640636871
        },
        {
            "type" : "quiz",
            "score" : 14.23233821353732
        },
        {
            "type" : "homework",
            "score" : 31.41421298576332
        },
        {
            "type" : "homework",
            "score" : 30.09304792394713
        }
    ]
}

我在Mongo shell上执行以下2个查询:

x=db.students.aggregate( [{ "$unwind":"$scores" },{"$match":{"scores.type":"homework"}},{ "$group":{"_id":"$_id","minscore":{"$min":"$scores.score" }}} ] )

,下一个是:

for (var a in x["a"]) { db.students.update( { "_id":a["_id"] },{"$pull":{"scores":{"score":a["minscore"]}}} ) }

我能够看到最低分数列表,但是当我执行第二个查询时似乎没有删除任何内容。我知道有一个逻辑错误。我试着阅读这里的帖子,但我无法通过它。我只是想知道我哪里出错了。

5 个答案:

答案 0 :(得分:4)

你的for循环中有几个问题 - 虽然你的聚合看起来不错。

您的结果文档“x”包含数组字段“result”。您想迭代该数组中的文档。您拥有的for循环语法不会在数组中设置值,而是在数组中设置索引。更好更清楚的是使用forEach循环语法:

x.result.forEach(function(doc) {
   db.students.update( { "_id": doc._id }, 
                       { "$pull": { "scores" : { 
                                          "score":doc.minscore, 
                                          "type":"homework"
                       } } } 
   );
});

您的更新声明也不太准确 - 您希望确保只拉出分数最低的作业 - 如果同一个学生的单个考试成绩相同,该怎么办?作为他们最低的功课?您的语法将拉出所有分数等于minscore的子文档!

那个很容易修复(并且我向您展示了仅用于提取家庭作业子文档的语法),但请记住与查询匹配的$pull will pull all values,如果只有一个作业,那么它就是minscore,它会被拉。如果有两个家庭作业但他们是平等的,他们会两个被拉!需要考虑的事情。

答案 1 :(得分:2)

使用以下代码删除最低分数。聚合代码没问题。

x=db.students.aggregate( [{ "$unwind":"$scores" },{"$match":{"scores.type":"homework"}},{ "$group":{"_id":"$_id","minscore":{"$min":"$scores.score" }}} ] );

var doc = myCursor.hasNext() ? x.next() : null;

x.forEach(function(doc) {db.students.update( { "_id": doc._id }, { "$pull": { "scores" : { 
"score":doc.minscore, "type":"homework"} } } );

在MongoShell上运行上面的代码后 - db.students.find.pretty(); 你会得到文件中的记录 -

{
    "_id" : 100,
    "name" : "Demarcus Audette",
    "scores" : [
        {
            "type" : "exam",
            "score" : 30.61740640636871
        },
        {
            "type" : "quiz",
            "score" : 14.23233821353732
        },
        {
            "type" : "homework",
            "score" : 31.41421298576332
        },
    ]
}

类型的最低分:"家庭作业"将从每个记录集中删除。

答案 2 :(得分:0)

这是因为当你这样做时:

x = db.students.aggregate([
  { "$unwind":"$scores" },
  {"$match":{
    "scores.type":"homework"
  }},
  { 
    "$group":{
       "_id":"$_id",
       "minscore":{"$min":"$scores.score" }}
    }
]);

您的结果采用以下形式:

{
  result : [{
    "_id" : 100,
    "minscore" : 30.09304792394713
  }],
  ok : 1
}

所以那里没有x["a"],你需要写x['result']

P.S。如果你正在做作业问题,你应该写下来。

答案 3 :(得分:0)

根据其他答案的组合,以下是与我合作的答案。

x = db.students.aggregate([
  { "$unwind":"$scores" },
  {"$match":{
    "scores.type":"homework"
  }},
  { 
    "$group":{
       "_id":"$_id",
       "minscore":{"$min":"$scores.score" }}
    }
]);



x.result.forEach(function(doc) {db.students.update( { "_id": doc._id },                         { "$pull": { "scores" : {
               "score":doc.minscore,"type":"homework" } } }); });

答案 4 :(得分:0)

以下代码为我工作。

var x=db.students.aggregate( [{ "$unwind":"$scores" },{"$match":{"scores.type":"homework"}},{"$group":{"_id":"$_id","minscore":{"$min":"$scores.score" }}} ] );

var doc = x.hasNext() ? x.next() : null;

x.forEach(function(doc){
    db.students.update( { "_id": doc._id }, { "$pull": { "scores" : { "score":doc.minscore, "type":"homework"} } } );
});