如何在mongoDB中对集合记录中的数组进行排序

the*_*nso 29 javascript arrays sorting mongodb

MongoDB noob在这里......

好的,我有一个学生集合,每个都有一个如下所示的记录....我想按照降序排序'类型':'家庭作业'分数.

那个咒语在mongo shell上是什么样的?

> db.students.find({'_id': 1}).pretty()
{
        "_id" : 1,
        "name" : "Aurelia Menendez",
        "scores" : [
                {
                        "type" : "exam",
                        "score" : 60.06045071030959
                },
                {
                        "type" : "quiz",
                        "score" : 52.79790691903873
                },
                {
                        "type" : "homework",
                        "score" : 71.76133439165544
                },
                {
                        "type" : "homework",
                        "score" : 34.85718117893772
                }
        ]
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试这个咒语....

 doc = db.students.find()

 for (_id,score) in doc.scores:
     print _id,score
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

Ste*_*nie 47

您需要在应用程序代码中操作嵌入式数组,或在MongoDB 2.2中使用新的聚合框架.

mongoshell中的示例聚合:

db.students.aggregate(
    // Initial document match (uses index, if a suitable one is available)
    { $match: {
        _id : 1
    }},

    // Expand the scores array into a stream of documents
    { $unwind: '$scores' },

    // Filter to 'homework' scores 
    { $match: {
        'scores.type': 'homework'
    }},

    // Sort in descending order
    { $sort: {
        'scores.score': -1
    }}
)
Run Code Online (Sandbox Code Playgroud)

样本输出:

{
    "result" : [
        {
            "_id" : 1,
            "name" : "Aurelia Menendez",
            "scores" : {
                "type" : "homework",
                "score" : 71.76133439165544
            }
        },
        {
            "_id" : 1,
            "name" : "Aurelia Menendez",
            "scores" : {
                "type" : "homework",
                "score" : 34.85718117893772
            }
        }
    ],
    "ok" : 1
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以更改聚合管道的末尾以按升序排序(因此最低值排在第一位)并限制为1个文档:`{$ sort:{'scores.score':1}},{$ limit:1} (3认同)

Xav*_*hot 17

从 开始Mongo 5.2,这就是新$sortArray聚合运算符的确切用例:

// {
//   name: "Aurelia Menendez",
//   scores: [
//     { type: "exam",     score: 60.06 }
//     { type: "quiz",     score: 52.79 }
//     { type: "homework", score: 71.76 }
//     { type: "homework", score: 34.85 }
//   ]
// }
db.collection.aggregate([
  { $set: {
    scores: {
      $sortArray: {
        input: "$scores",
        sortBy: { score: -1 }
      }
    }
  }}
])
// {
//   name: "Aurelia Menendez",
//   scores: [
//     { type: "homework", score: 71.76 },
//     { type: "exam",     score: 60.06 },
//     { type: "quiz",     score: 52.79 },
//     { type: "homework", score: 34.85 }
//   ]
// }
Run Code Online (Sandbox Code Playgroud)

这:

  • 对 ( $sortArray)scores数组进行排序 ( input: "$scores")
  • score通过对s ( sortBy: { score: -1 })进行排序
  • 无需应用昂贵的$unwind,$sort$group阶段的组合

  • 这是给定问题的**唯一**正确答案。所有其他答案都使用不同的输入数据或更新现有数据或删除分数,而不是对数组进行排序或使用不同的语言,尽管它要求 mongo shell。 (3认同)
  • @RyanAquino [整数数组排序](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sortArray/#sort-an-array-of-integers) (2认同)

Dan*_*one 9

由于可以通过不同方式管理这个问题,我想说另一种解决方案是“插入和排序”,这样您将在进行 Find() 时获得 Ordered 数组。

考虑这个数据:

{
   "_id" : 5,
   "quizzes" : [
      { "wk": 1, "score" : 10 },
      { "wk": 2, "score" : 8 },
      { "wk": 3, "score" : 5 },
      { "wk": 4, "score" : 6 }
   ]
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们将更新文档,进行排序。

db.students.update(
   { _id: 5 },
   {
     $push: {
       quizzes: {
          $each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],
          $sort: { score: -1 },
          $slice: 3 // keep the first 3 values
       }
     }
   }
)
Run Code Online (Sandbox Code Playgroud)

结果是:

{
  "_id" : 5,
  "quizzes" : [
     { "wk" : 1, "score" : 10 },
     { "wk" : 2, "score" : 8 },
     { "wk" : 5, "score" : 8 }
  ]
}
Run Code Online (Sandbox Code Playgroud)

文档:https : //docs.mongodb.com/manual/reference/operator/update/sort/#up._S_sort


Ale*_*yuk 7

这就是我们用JS和mongo控制台解决这个问题的方法:

db.students.find({"scores.type": "homework"}).forEach(
  function(s){
    var sortedScores = s.scores.sort(
      function(a, b){
        return a.score<b.score && a.type=="homework";
      }
    );
    var lowestHomeworkScore = sortedScores[sortedScores.length-1].score;
    db.students.update({_id: s._id},{$pull: {scores: {score: lowestHomeworkScore}}}, {multi: true});
  })
Run Code Online (Sandbox Code Playgroud)

  • 杜德?您破坏了乐趣。 (2认同)