【问题标题】:How do I sort a collection based on values in an array如何根据数组中的值对集合进行排序
【发布时间】:2014-08-29 21:47:13
【问题描述】:

我的集合命名结果具有以下值:-

> db.result.findOne()
{
        "_id" : ObjectId("53b05264421aa97e980ba404"),
        "result" : [
                {
                        "attempted" : 49,
                        "subject_total_marks" : 50,
                        "score" : 15,
                        "correct_subject_answer" : 15,
                        "subject" : "Biology"
                },
                {
                        "attempted" : 30,
                        "subject_total_marks" : 30,
                        "score" : 4,
                        "correct_subject_answer" : 4,
                        "subject" : "Chemistry"
                },
                {
                        "attempted" : 20,
                        "subject_total_marks" : 20,
                        "score" : 7,
                        "correct_subject_answer" : 7,
                        "subject" : "Physics"
                },
                {
                        "attempted" : 99,
                        "correct_subject_answer" : 26,
                        "score" : 26,
                        "subject_total_marks" : 100,
                        "subject" : "Total"
                }
        ],
        "useruid" : NumberLong(548),
        "exam_code" : 301,
        "ess_time" : 1404062120
}

现在我想根据结果数组中的“总分”的“分数”对集合进行排序。然后根据物理,数学的分数排序,然后根据化学,最后是生物学。

【问题讨论】:

  • 你应该为一个好问题投赞成票,因为显然反对者​​不明白你不能只应用 .sort() 修饰符和 .find() 来做到这一点。还编辑了您的标题以明确这一点。
  • @NeilLunn 感谢您的编辑...但是该怎么做呢?

标签: python mongodb sorting mongodb-query aggregation-framework


【解决方案1】:

正如您可能已经尝试过的那样,您不能将数组中的特定项目指定为通过简单查找“排序”的“键”。为此,您将需要聚合方法来获取要排序的键。

db.exam.aggregate([

     # Unwind to de-normalize
     { "$unwind": "$result" },

     # Group back to the document and extract each score
     { "$group": {
         "_id": "$_id",
         "result": { "$push": "$result" },
         "useruid": { "$first": "$useruid" },
         "exam_code": { "$first": "$exam_code" },
         "ess_time": { "$first": "$ess_time" },
         "Total": { 
             "$max": {
                 "$cond": [
                     { "$eq": [ "$result.subject", "Total" ] },
                     "$result.score",
                     0
                 ]
             }
         },
         "Physics": { 
             "$max": {
                 "$cond": [
                     { "$eq": [ "$result.subject", "Physics" ] },
                     "$result.score",
                     0
                 ]
             }
         },
         "Mathematics": { 
             "$max": {
                 "$cond": [
                     { "$eq": [ "$result.subject", "Mathematics" ] },
                     "$result.score",
                     0
                 ]
             }
         },
         "Chemistry": { 
             "$max": {
                 "$cond": [
                     { "$eq": [ "$result.subject", "Chemistry" ] },
                     "$result.score",
                     0
                 ]
             }
         },
         "Biology": { 
             "$max": {
                 "$cond": [
                     { "$eq": [ "$result.subject", "Biology" ] },
                     "$result.score",
                     0
                 ]
             }
         }
     }},

     # Sort on those scores
     { "$sort": {
         "Total": -1,
         "Physics": -1,
         "Mathematics": -1,
         "Chemistry": -1,
         "Biology": -1
     }},

     # Project final wanted fields
     { "$project": {
         "result": 1,
         "useruid": 1,
         "exam_code": 1,
         "ess_time": 1
     }}
])

因此,在展开数组后,您可以在 $max 语句中使用 $cond 运算符“提取”匹配值。去规范化的文档并不都具有相同的值,因为它们现在表示数组中的项目,因此您需要对其进行测试。

使用这些提取的键,您可以再次对整个文档进行排序,然后最终丢弃那些不再需要的字段。

【讨论】:

  • 这是一个很棒的解决方案......谢谢你 Neil.. 非常感谢你的解决方案
猜你喜欢
  • 2021-12-10
  • 2018-03-05
  • 2022-07-19
  • 2011-03-29
  • 1970-01-01
  • 2015-08-31
  • 2016-07-12
  • 1970-01-01
相关资源
最近更新 更多