2014-06-18 4 views
1

나는 이벤트라고 불리는 mongodb 콜렉션을 가지고 있는데, 여기에는 야구 게임이 들어있다. 나는 모든 팀의 순위를 반환하는 쿼리를 작성하는 데 도움이 필요MongoDB : 하위 문서의 배열에서 필드 집계

{ 
    "name" : "Game# 814", 
    "dateStart" : ISODate("2012-09-28T14:47:53.695Z"), 
    "_id" : ObjectId("53a1b24de3f25f4443d9747e"), 
    "stats" : [ 
     { 
      "team" : ObjectId("53a11a43a8de6dd8375c940b"), 
      "teamName" : "Reds", 
      "_id" : ObjectId("53a1b24de3f25f4443d97480"), 
      "score" : 17 
     }, 
     { 
      "team" : ObjectId("53a11a43a8de6dd8375c938d"), 
      "teamName" : "Yankees", 
      "_id" : ObjectId("53a1b24de3f25f4443d9747f"), 
      "score" : 12 
     } 
    ] 
    "__v" : 0 
} 

다음은 테이블의 한 레코드의 예입니다. 여기

{ 
    "team" : ObjectId("53a11a43a8de6dd8375c938d"), 
    "teamName" : "Yankees", 
    "wins" : <<number of Yankees wins>> 
    "losses" : <<number of Yankees losses>> 
    "draws" : <<number of Yankees draws>> 
} 
{ 
    "team" : ObjectId("53a11a43a8de6dd8375c940b"), 
    "teamName" : "Reds", 
    "wins" : <<number of Reds wins>> 
    "losses" : <<number of Reds losses>> 
    "draws" : <<number of Reds draws>> 
} 
... 

내가 시작했습니다 쿼리의

db.events.aggregate(
    {"$unwind": "$stats" }, 
    { $group : { 
     _id : "$stats.team", 
     gamesPlayed : { $sum : 1}, 
     totalScore : { $sum : "$stats.score" } 
    }} 
); 

... 어떤 결과를 반환 ... :

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("53a11a43a8de6dd8375c93cb"), 
      "gamesPlayed" : 125, // not a requirement... just trying to get $sum working 
      "totalScore" : 1213 // ...same here 
     }, 
     { 
      "_id" : ObjectId("53a11a44a8de6dd8375c955f"), 
      "gamesPlayed" : 128, 
      "totalScore" : 1276 
     }, 
     { 
      "_id" : ObjectId("53a11a44a8de6dd8375c9661"), 
      "gamesPlayed" : 152, 
      "totalScore" : 1509 
     }, 
.... 
+0

지금까지 사용해 본 모든 것이 있습니까? 'db.events.aggregate ( : – peter

+0

이 쿼리를 사용하여 { "$의 풀림을": "$ 통계를"}, {$ 그룹 : { _id : "$의 stats.team을" gamesPlayed : {$ 합계 : 1}, totalScore : {$ sum : "$ stats.score"} }} ); { "결과": [ { "_id": ObjectId가 ("53a11a43a8de6dd8375c93cb"), "gamesPlayed": 125, "totalScore"1213 ' 는이 같은 결과를 얻을 수 있어요 }, \t ... 하지만 다시 그룹화하는 방법을 알지 못하고 각 게임의 승패 상황을 파악합니다. – user3662896

+0

서식을 보내 주셔서 감사합니다. blerg – user3662896

답변

1

그것은 바람직 것 같다을 같이 결과 집합이 보일 것입니다 귀하가 문서를 작성하거나 업데이트 할 때 "승", "손실", "무승부"를 유지할 수 있습니다. 약간은 긴 호흡 경우 집계와 함께 할 수

db.events.aggregate([ 

    // Unwind the "stats" array 
    { "$unwind": "$stats" }, 

    // Combine the document with new fields 
    { "$group": { 
     "_id": "$_id", 
     "firstTeam": { "$first": "$stats.team" }, 
     "firstTeamName": { "$first": "$stats.teamName" }, 
     "firstScore": { "$first": "$stats.score" }, 
     "lastTeam": { "$last": "$stats.team" }, 
     "lastTeamName": { "$last": "$stats.teamName" }, 
     "lastScore": { "$last": "$stats.score" }, 
     "minScore": { "$min": "$stats.score" }, 
     "maxScore": { "$max": "$stats.score" } 
    }}, 

    // Calculate by comparing scores 
    { "$project": { 
     "firstTeam": 1, 
     "firstTeamName": 1, 
     "firstScore": 1, 
     "lastTeam": 1, 
     "lastTeamName": 1, 
     "lastScore": 1, 
     "firstWins": { 
      "$cond": [ 
       { "$gt": [ "$firstScore", "$lastScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "firstLosses": { 
      "$cond": [ 
       { "$lt": [ "$firstScore", "$lastScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "firstDraws": { 
      "$cond": [ 
       { "$eq": [ "$firstScore", "$lastScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "lastWins": { 
      "$cond": [ 
       { "$gt": [ "$lastScore", "$firstScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "lastLosses": { 
      "$cond": [ 
       { "$lt": [ "$lastScore", "$firstScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "lastDraws": { 
      "$cond": [ 
       { "$eq": [ "$lastScore", "$firstScore" ] }, 
       1, 
       0 
      ] 
     }, 
     "type": { "$literal": [ true, false ] } 
    }}, 

    // Unwind the "type" 
    { "$unwind": "$type" }, 


    // Group teams conditionally on "type" 
    { "$group": { 
     "_id": { 
      "team": { 
       "$cond": [ 
        "$type", 
        "$firstTeam", 
        "$lastTeam" 
       ] 
      }, 
      "teamName": { 
       "$cond": [ 
        "$type", 
        "$firstTeamName", 
        "$lastTeamName" 
       ] 
      } 
     },    
     "owins": { 
      "$sum": { 
       "$cond": [ 
        "$type", 
        "$firstWins", 
        "$lastWins" 
       ] 
      } 
     }, 
     "olosses": { 
      "$sum": { 
       "$cond": [ 
        "$type", 
        "$firstLosses", 
        "$lastLosses" 
       ] 
      } 
     }, 
     "odraws": { 
      "$sum": { 
       "$cond": [ 
        "$type", 
        "$firstDraws", 
        "$lastDraws" 
       ] 
      } 
     } 
    }}, 

    // Project your final form 
    { "$project": { 
     "_id": 0, 
     "team": "$_id.team", 
     "teamName": "$_id.teamName", 
     "wins": "$owins", 
     "losses": "$olosses", 
     "draws": "$odraws" 
    }} 

]) 

첫 번째 부분은은 "처음"과 "마지막"로 그룹화 한 후 배열을 풀어서하여 "재 모양의"문서에 두 팀의 필드를 정의합니다.

그런 다음 해당 문서를 통해 $project을 입력하고 페어링에서 각 팀의 "승리", "손실"및 "무승부"를 계산하십시오. 추가 사항은 여기에 편리한 두 값인 true/false에 대한 배열 필드를 추가하는 것입니다. mongodb 2.6 이전 버전을 사용하는 경우 $literal$const으로 바꿀 수 있습니다.이 내용은 문서화되어 있지는 않지만 동일한 내용입니다.

는 "유형"배열이 문서는 "첫 번째"선택하거나 $cond의 사용을 통해 "마지막"팀 필드 값 여부를 평가하여 $group 단계에 떨어져 분리 될 수 있음을 $unwind되면. 이것은 true/false 조건을 평가하고 해당 조건에 따라 적절한 값을 반환하는 삼항 연산자입니다.

최종본 $project으로 문서는 원하는대로 정확하게 구성됩니다.

+0

감사합니다 닐, 이건 훌륭해. 그리고 나는 그 설명을 고맙게 생각한다.작성/업데이트 할 때 반드시 결과를 문서로 옮기는 것을 고려할 것입니다. – user3662896

관련 문제