3

这是我的收藏的样子:

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"]}}} ) }

我可以看到最低分数列表,但是当我执行第二个查询时,似乎什么都没有被删除。我知道有一个逻辑错误。我试图阅读这里的帖子,但我无法通过它。我只是想知道我哪里出错了。

4

5 回答 5

4

您的 for 循环中有几个问题 - 尽管您的聚合看起来不错。

您的结果文档“x”包含一个数组字段“result”。您想遍历该数组中的文档。您使用的 for 循环语法不会将 a 设置为数组中的值,而是设置为数组中的索引。更好更清晰的是使用 forEach 循环语法:

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

您的更新声明也不太准确 - 您想确保只提取得分最低的家庭作业- 如果同一个学生的一次考试也与他们的最低家庭作业得分相同怎么办?您的语法将提取所有分数等于 minscore 的子文档!

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

于 2013-10-29T05:17:47.330 回答
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
        },
    ]
}

类型的最低分数:“作业”将从每个记录集中删除。

于 2014-06-19T12:52:08.060 回答
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'].

PS如果你在做作业题,你应该写下来。

于 2013-10-29T01:42:30.230 回答
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" } } }); });
于 2015-10-29T13:02:59.040 回答
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"} } } );
});
于 2016-01-25T00:48:26.757 回答