How do I sort a collection based on values in an array

这一生的挚爱 提交于 2019-12-14 03:52:48

问题


I have collection named result with following values:-

> 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
}

Now I want to sort the collection based on "score" of "total" which is inside result array. Then sort based on score of physics, mathematics and then based on chemistry and finally biology.


回答1:


As you may have already tried, you cannot specify a specific item inside an array as a "key" to "sort" with a simple find. For this you are going to need the aggregate method in order to get the keys you want to sort on.

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

So here you "extract" the matching values using the $cond operator within a $max statement after unwinding the array. The de-normalized documents do not all have the same values as they now represent the items in the array, so you test them.

With those extracted keys you can sort your whole documents again, and then finally discard those fields as you no longer need them.



来源:https://stackoverflow.com/questions/24644005/how-do-i-sort-a-collection-based-on-values-in-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!