【问题标题】:Conditionally Aggregate Against Choice of Pairs : Home or Away有条件地根据对的选择聚合:主场或客场
【发布时间】:2017-07-25 20:08:45
【问题描述】:

我正在寻找将足球比赛汇总到汇总表中以显示资格表的最佳方式。我的数据如下所示:

/* 1 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4fb"),
    "home" : ObjectId("596fe03ad496e047d6314bf7"),
    "away" : ObjectId("596fe03ad496e047d6314be8"),
    "homeGoals" : 4,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-28T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 2 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4fd"),
    "home" : ObjectId("596fe03ad496e047d6314be9"),
    "away" : ObjectId("596fe03ad496e047d6314c0d"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-29T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 3 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f502"),
    "home" : ObjectId("596fe03ad496e047d6314bed"),
    "away" : ObjectId("596fe03ad496e047d6314c0f"),
    "homeGoals" : 4,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-05-18T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 4 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4fe"),
    "home" : ObjectId("596fe03ad496e047d6314c13"),
    "away" : ObjectId("596fe03ad496e047d6314bee"),
    "homeGoals" : 1,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-29T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 5 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f503"),
    "home" : ObjectId("596fe03ad496e047d6314c1c"),
    "away" : ObjectId("596fe03ad496e047d6314be9"),
    "homeGoals" : 1,
    "awayGoals" : 3,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-03T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 6 */
{
    "_id" : ObjectId("5976b6e0f42aa4d69585f4fa"),
    "home" : ObjectId("596fe03ad496e047d6314c30"),
    "away" : ObjectId("596fe03ad496e047d6314bfe"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-28T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 7 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4ff"),
    "home" : ObjectId("596fe03ad496e047d6314c21"),
    "away" : ObjectId("596fe03ad496e047d6314bf4"),
    "homeGoals" : 0,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-29T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 8 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4fc"),
    "home" : ObjectId("596fe03ad496e047d6314bdb"),
    "away" : ObjectId("596fe03ad496e047d6314bf6"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-28T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 9 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f500"),
    "home" : ObjectId("596fe03ad496e047d6314c2d"),
    "away" : ObjectId("596fe03ad496e047d6314be0"),
    "homeGoals" : 3,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-01-29T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 10 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f504"),
    "home" : ObjectId("596fe03ad496e047d6314bf4"),
    "away" : ObjectId("596fe03ad496e047d6314c30"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-03T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 11 */
{
    "_id" : ObjectId("5976b6e1f42aa4d69585f501"),
    "home" : ObjectId("596fe03ad496e047d6314bfa"),
    "away" : ObjectId("596fe03ad496e047d6314c1c"),
    "homeGoals" : 1,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b3"),
    "date" : ISODate("2017-03-25T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 12 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f505"),
    "home" : ObjectId("596fe03ad496e047d6314be0"),
    "away" : ObjectId("596fe03ad496e047d6314c13"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-05T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 13 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f506"),
    "home" : ObjectId("596fe03ad496e047d6314be0"),
    "away" : ObjectId("596fe03ad496e047d6314bee"),
    "homeGoals" : 2,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-11T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 14 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f507"),
    "home" : ObjectId("596fe03ad496e047d6314c13"),
    "away" : ObjectId("596fe03ad496e047d6314c30"),
    "homeGoals" : 3,
    "awayGoals" : 4,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 15 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50c"),
    "home" : ObjectId("596fe03ad496e047d6314be8"),
    "away" : ObjectId("596fe03ad496e047d6314bfa"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-04T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 16 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f511"),
    "home" : ObjectId("596fe03ad496e047d6314be0"),
    "away" : ObjectId("596fe03ad496e047d6314bf4"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-23T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 17 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f516"),
    "home" : ObjectId("596fe03ad496e047d6314be9"),
    "away" : ObjectId("596fe03ad496e047d6314bfa"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 18 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50a"),
    "home" : ObjectId("596fe03ad496e047d6314c13"),
    "away" : ObjectId("596fe03ad496e047d6314c0f"),
    "homeGoals" : 4,
    "awayGoals" : 3,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-25T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 19 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50b"),
    "home" : ObjectId("596fe03ad496e047d6314bf7"),
    "away" : ObjectId("596fe03ad496e047d6314bdb"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-04T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 20 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51b"),
    "home" : ObjectId("596fe03ad496e047d6314be8"),
    "away" : ObjectId("596fe03ad496e047d6314bf6"),
    "homeGoals" : 2,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-05T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 21 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50f"),
    "home" : ObjectId("596fe03ad496e047d6314bee"),
    "away" : ObjectId("596fe03ad496e047d6314c1c"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-13T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 22 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f520"),
    "home" : ObjectId("596fe03ad496e047d6314bfa"),
    "away" : ObjectId("596fe03ad496e047d6314bf7"),
    "homeGoals" : 2,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-19T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 23 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f514"),
    "home" : ObjectId("596fe03ad496e047d6314bfe"),
    "away" : ObjectId("596fe03ad496e047d6314c21"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-05T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 24 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f510"),
    "home" : ObjectId("596fe03ad496e047d6314c0d"),
    "away" : ObjectId("596fe03ad496e047d6314be0"),
    "homeGoals" : 0,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-19T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 25 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f519"),
    "home" : ObjectId("596fe03ad496e047d6314bf6"),
    "away" : ObjectId("596fe03ad496e047d6314c30"),
    "homeGoals" : 1,
    "awayGoals" : 3,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-25T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 26 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f515"),
    "home" : ObjectId("596fe03ad496e047d6314c2d"),
    "away" : ObjectId("596fe03ad496e047d6314c0f"),
    "homeGoals" : 1,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-10T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 27 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51e"),
    "home" : ObjectId("596fe03ad496e047d6314c21"),
    "away" : ObjectId("596fe03ad496e047d6314be8"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 28 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51a"),
    "home" : ObjectId("596fe03ad496e047d6314c2d"),
    "away" : ObjectId("596fe03ad496e047d6314bfe"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-27T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 29 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51f"),
    "home" : ObjectId("596fe03ad496e047d6314c30"),
    "away" : ObjectId("596fe03ad496e047d6314bdb"),
    "homeGoals" : 2,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-17T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 30 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f508"),
    "home" : ObjectId("596fe03ad496e047d6314bfe"),
    "away" : ObjectId("596fe03ad496e047d6314c13"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-19T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 31 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50d"),
    "home" : ObjectId("596fe03ad496e047d6314bee"),
    "away" : ObjectId("596fe03ad496e047d6314bf7"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-06T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 32 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f512"),
    "home" : ObjectId("596fe03ad496e047d6314c21"),
    "away" : ObjectId("596fe03ad496e047d6314bfa"),
    "homeGoals" : 0,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-26T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 33 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f517"),
    "home" : ObjectId("596fe03ad496e047d6314c0f"),
    "away" : ObjectId("596fe03ad496e047d6314c21"),
    "homeGoals" : 4,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-18T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 34 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51c"),
    "home" : ObjectId("596fe03ad496e047d6314c0f"),
    "away" : ObjectId("596fe03ad496e047d6314bdb"),
    "homeGoals" : 2,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-02-04T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 35 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f521"),
    "home" : ObjectId("596fe03ad496e047d6314bf7"),
    "away" : ObjectId("596fe03ad496e047d6314be9"),
    "homeGoals" : 2,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-24T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 36 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f509"),
    "home" : ObjectId("596fe03ad496e047d6314bee"),
    "away" : ObjectId("596fe03ad496e047d6314c2d"),
    "homeGoals" : 1,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-20T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 37 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f50e"),
    "home" : ObjectId("596fe03ad496e047d6314bf7"),
    "away" : ObjectId("596fe03ad496e047d6314bfe"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b5"),
    "date" : ISODate("2017-02-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 38 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f513"),
    "home" : ObjectId("596fe03ad496e047d6314c0f"),
    "away" : ObjectId("596fe03ad496e047d6314c0d"),
    "homeGoals" : 2,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-04T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 39 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f518"),
    "home" : ObjectId("596fe03ad496e047d6314c1c"),
    "away" : ObjectId("596fe03ad496e047d6314bf6"),
    "homeGoals" : 0,
    "awayGoals" : 3,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b6"),
    "date" : ISODate("2017-02-19T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 40 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f51d"),
    "home" : ObjectId("596fe03ad496e047d6314bf6"),
    "away" : ObjectId("596fe03ad496e047d6314bed"),
    "homeGoals" : 0,
    "awayGoals" : 4,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b4"),
    "date" : ISODate("2017-04-05T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 41 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f522"),
    "home" : ObjectId("596fe03ad496e047d6314bdb"),
    "away" : ObjectId("596fe03ad496e047d6314c1c"),
    "homeGoals" : 6,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b7"),
    "date" : ISODate("2017-02-27T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 42 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f523"),
    "home" : ObjectId("596fe03ad496e047d6314bfa"),
    "away" : ObjectId("596fe03ad496e047d6314bed"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-05T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 43 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f524"),
    "home" : ObjectId("596fe03ad496e047d6314bdb"),
    "away" : ObjectId("596fe03ad496e047d6314be8"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b9"),
    "date" : ISODate("2017-03-11T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 44 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f528"),
    "home" : ObjectId("596fe03ad496e047d6314bed"),
    "away" : ObjectId("596fe03ad496e047d6314be9"),
    "homeGoals" : 1,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b9"),
    "date" : ISODate("2017-03-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 45 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f526"),
    "home" : ObjectId("596fe03ad496e047d6314bf6"),
    "away" : ObjectId("596fe03ad496e047d6314bfa"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b9"),
    "date" : ISODate("2017-03-11T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 46 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f525"),
    "home" : ObjectId("596fe03ad496e047d6314bf4"),
    "away" : ObjectId("596fe03ad496e047d6314c2d"),
    "homeGoals" : 2,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-22T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 47 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f529"),
    "home" : ObjectId("596fe03ad496e047d6314bfe"),
    "away" : ObjectId("596fe03ad496e047d6314be0"),
    "homeGoals" : 1,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-05T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 48 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f52b"),
    "home" : ObjectId("596fe03ad496e047d6314c21"),
    "away" : ObjectId("596fe03ad496e047d6314bf7"),
    "homeGoals" : 2,
    "awayGoals" : 1,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b9"),
    "date" : ISODate("2017-03-12T08:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 49 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f527"),
    "home" : ObjectId("596fe03ad496e047d6314c30"),
    "away" : ObjectId("596fe03ad496e047d6314bee"),
    "homeGoals" : 3,
    "awayGoals" : 0,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-05-03T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

/* 50 */
{
    "_id" : ObjectId("5976b6e2f42aa4d69585f52a"),
    "home" : ObjectId("596fe03ad496e047d6314be9"),
    "away" : ObjectId("596fe03ad496e047d6314c21"),
    "homeGoals" : 1,
    "awayGoals" : 2,
    "tournament" : ObjectId("59726e597ec27162718ff90b"),
    "stage" : ObjectId("59726e597ec27162718ff9b8"),
    "date" : ISODate("2017-03-23T07:00:00.000Z"),
    "notes" : "",
    "__v" : 0
}

Home 和 Away 是球队的 ID,homeGoals 和 awayGoals 是比赛的比分。这些是我需要写的查询的主要参与者。在某些比赛中,A队是主队,而在另一些比赛中,A队是客队。但我需要像这样聚合这张表:

Team   | Games Played | Games Won | Games Lost | Games Drawn | Goals For | Goals Against | Goal Differential | Points
------ | ------------ | --------- | ---------- | ----------- | --------- | ------------- | ----------------- | ------
Team A | 10           | 6         | 3          | 1           | 10        | 3             | 7                 | 21    
Team B | 10           | 5         | 3          | 2           | 11        | 5             | 6                 | 18

我需要一种按 ID 组合团队的方法,无论他们是主队还是客队,总结他们的目标,并计算差异。

什么是使用猫鼬查询实现此目的的好方法,而不必查询所有内容并使用reduce或类似的东西。

任何帮助将不胜感激。提前致谢。

【问题讨论】:

  • 我相信您正试图强迫 MongoDB 像关系数据库一样工作,这从您文档中各处的 ObjectId(...) 引用中可以明显看出。这不是自然的 MongoDB 设计模式,并且导致难以用简单的术语表达您的需求。我建议您重新考虑您的架构设计。例如,如果这个聚合结果是你一直需要的,你应该调整你的 MongoDB 模式模型以支持简单的聚合。有关示例,请参阅docs.mongodb.com/ecosystem/use-cases
  • 你可能有一个观点。我真正熟悉的是SQL DB。我将尝试重新考虑架构。谢谢!

标签: mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

我个人会“预先汇总”每支球队的结果,并在每场比赛结束后更新它们,并酌情增加每个计数器。但是这里仍然没有结构上的错误,只是本质上将“每场比赛”视为每支球队的单独记录。

这很容易通过将$map 应用到每个团队,并根据正在处理的值选择适当的“home”或“away”值来完成。所以你这里的主要“朋友”是$cond“三元”表达式,它允许你有选择地返回值:

db.games.aggregate([
  { "$project": {
    "teams": {
      "$map": {
        "input": ["$home","$away"],
        "as": "t",
        "in": {
          "team": "$$t",
          "played": 1,
          "win": {
            "$cond": {
              "if": {
                "$or": [
                  { "$and": [
                    { "$eq": [ "$$t", "$home" ] },
                    { "$gt": [ "$homeGoals", "$awayGoals" ] }   
                  ]},
                 { "$and": [
                   { "$eq": [ "$$t", "$away" ] },
                   { "$gt": [ "$awayGoals", "$homeGoals" ] }   
                 ]} 
                ]
              },
              "then": 1,
              "else": 0    
            }
          },
          "lost": {
            "$cond": {
              "if": {
                "$or": [
                  { "$and": [
                    { "$eq": [ "$$t", "$home" ] },
                    { "$lt": [ "$homeGoals", "$awayGoals" ] }   
                  ]},
                 { "$and": [
                   { "$eq": [ "$$t", "$away" ] },
                   { "$lt": [ "$awayGoals", "$homeGoals" ] }   
                 ]} 
                ]
              },
              "then": 1,
              "else": 0    
            }
          },
          "draw": {
            "$cond": {
              "if": {
                "$eq": ["$homeGoals","$awayGoals"]
              },
              "then": 1,
              "else": 0    
            }
          },
          "goalsFor": {
            "$cond": {
              "if": { "$eq": [ "$$t", "$home" ] },
              "then": "$homeGoals",
              "else": "$awayGoals"
            }    
          },
          "goalsAgainst": {
            "$cond": {
              "if": { "$eq": [ "$$t", "$away" ] },
              "then": "$homeGoals",
              "else": "$awayGoals"
            }    
          }
        }
      }    
    }
  }},
  { "$unwind": "$teams" },
  { "$group": {
    "_id": "$teams.team",
    "played": { "$sum": "$teams.played" },
    "win": { "$sum": "$teams.win" },
    "lost": { "$sum": "$teams.lost" },
    "draw": { "$sum": "$teams.draw" },
    "goalsFor": { "$sum": "$teams.goalsFor" },
    "goalsAgainst": { "$sum": "$teams.goalsAgainst" }
  }},
  { "$addFields": {
    "goalDifferential": {
      "$abs": { 
        "$subtract": [ "$goalsFor", "$goalsAgainst" ]
      }
    },
    "points": {
      "$add": [
        { "$multiply": [ "$win", 3 ] },
        "$draw"  
      ]
    }    
  }},
  { "$sort": { "points": -1, "goalDifferential": 1 } }
])

因此,如果您通过 $map 操作从最初的 $project 中查看“纯粹”,并在该数组中投影不同的字段,则每个“游戏”都将转换为以下内容:

{
    "_id" : ObjectId("5976b6e1f42aa4d69585f4fb"),
    "teams" : [ 
        {
            "team" : ObjectId("596fe03ad496e047d6314bf7"),
            "played" : 1.0,
            "win" : 1.0,
            "lost" : 0.0,
            "draw" : 0.0,
            "goalsFor" : 4.0,
            "goalsAgainst" : 1.0
        }, 
        {
            "team" : ObjectId("596fe03ad496e047d6314be8"),
            "played" : 1.0,
            "win" : 0.0,
            "lost" : 1.0,
            "draw" : 0.0,
            "goalsFor" : 1.0,
            "goalsAgainst" : 4.0
        }
    ]
}

这有效地将每场比赛变成了“两组”结果,即从“每个团队”的角度来看的一组结果。

从那里开始,这是相当标准的票价,您可以在其中 $unwind 数组,以便通过每个“团队”标识符 $group,累积结果。

对于附加字段,您可以在完成分组“之后”计算这些字段,或者根据需要将它们包含在初始投影和分组中。我在这里的解释将3 指向“获胜”,1 指向每个“平局”,然后考虑“绝对”差异,以便将$sort 排名应用于排行榜,并对这些进行一些区分具有相同“点”的团队。

当然你可以做任何你想做的事,但这里的主要原则是使用$map为每场比赛的每个参赛球队创建一个结果“数组”,并使用$cond区分“ home”和“away”,从而记录适当的值。

提供的 50 场比赛样本的总体结果包括输出中的 18 个不同球队:

/* 1 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bfa"),
    "played" : 7.0,
    "win" : 4.0,
    "lost" : 0.0,
    "draw" : 3.0,
    "goalsFor" : 10.0,
    "goalsAgainst" : 6.0,
    "goalDifferential" : 4.0,
    "points" : 15.0
}

/* 2 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c30"),
    "played" : 6.0,
    "win" : 4.0,
    "lost" : 1.0,
    "draw" : 1.0,
    "goalsFor" : 15.0,
    "goalsAgainst" : 9.0,
    "goalDifferential" : 6.0,
    "points" : 13.0
}

/* 3 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bf7"),
    "played" : 7.0,
    "win" : 3.0,
    "lost" : 2.0,
    "draw" : 2.0,
    "goalsFor" : 10.0,
    "goalsAgainst" : 7.0,
    "goalDifferential" : 3.0,
    "points" : 11.0
}

/* 4 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bdb"),
    "played" : 6.0,
    "win" : 3.0,
    "lost" : 1.0,
    "draw" : 2.0,
    "goalsFor" : 11.0,
    "goalsAgainst" : 4.0,
    "goalDifferential" : 7.0,
    "points" : 11.0
}

/* 5 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c0f"),
    "played" : 6.0,
    "win" : 3.0,
    "lost" : 2.0,
    "draw" : 1.0,
    "goalsFor" : 12.0,
    "goalsAgainst" : 12.0,
    "goalDifferential" : 0.0,
    "points" : 10.0
}

/* 6 */
{
    "_id" : ObjectId("596fe03ad496e047d6314be0"),
    "played" : 6.0,
    "win" : 2.0,
    "lost" : 1.0,
    "draw" : 3.0,
    "goalsFor" : 6.0,
    "goalsAgainst" : 5.0,
    "goalDifferential" : 1.0,
    "points" : 9.0
}

/* 7 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bed"),
    "played" : 4.0,
    "win" : 3.0,
    "lost" : 1.0,
    "draw" : 0.0,
    "goalsFor" : 9.0,
    "goalsAgainst" : 1.0,
    "goalDifferential" : 8.0,
    "points" : 9.0
}

/* 8 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c2d"),
    "played" : 5.0,
    "win" : 2.0,
    "lost" : 1.0,
    "draw" : 2.0,
    "goalsFor" : 6.0,
    "goalsAgainst" : 5.0,
    "goalDifferential" : 1.0,
    "points" : 8.0
}

/* 9 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c21"),
    "played" : 7.0,
    "win" : 2.0,
    "lost" : 3.0,
    "draw" : 2.0,
    "goalsFor" : 6.0,
    "goalsAgainst" : 10.0,
    "goalDifferential" : 4.0,
    "points" : 8.0
}

/* 10 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bf4"),
    "played" : 4.0,
    "win" : 2.0,
    "lost" : 1.0,
    "draw" : 1.0,
    "goalsFor" : 5.0,
    "goalsAgainst" : 2.0,
    "goalDifferential" : 3.0,
    "points" : 7.0
}

/* 11 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c13"),
    "played" : 5.0,
    "win" : 1.0,
    "lost" : 1.0,
    "draw" : 3.0,
    "goalsFor" : 8.0,
    "goalsAgainst" : 8.0,
    "goalDifferential" : 0.0,
    "points" : 6.0
}

/* 12 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bfe"),
    "played" : 6.0,
    "win" : 1.0,
    "lost" : 2.0,
    "draw" : 3.0,
    "goalsFor" : 3.0,
    "goalsAgainst" : 4.0,
    "goalDifferential" : 1.0,
    "points" : 6.0
}

/* 13 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bee"),
    "played" : 6.0,
    "win" : 1.0,
    "lost" : 2.0,
    "draw" : 3.0,
    "goalsFor" : 4.0,
    "goalsAgainst" : 7.0,
    "goalDifferential" : 3.0,
    "points" : 6.0
}

/* 14 */
{
    "_id" : ObjectId("596fe03ad496e047d6314be9"),
    "played" : 6.0,
    "win" : 1.0,
    "lost" : 4.0,
    "draw" : 1.0,
    "goalsFor" : 6.0,
    "goalsAgainst" : 8.0,
    "goalDifferential" : 2.0,
    "points" : 4.0
}

/* 15 */
{
    "_id" : ObjectId("596fe03ad496e047d6314be8"),
    "played" : 5.0,
    "win" : 1.0,
    "lost" : 3.0,
    "draw" : 1.0,
    "goalsFor" : 6.0,
    "goalsAgainst" : 10.0,
    "goalDifferential" : 4.0,
    "points" : 4.0
}

/* 16 */
{
    "_id" : ObjectId("596fe03ad496e047d6314bf6"),
    "played" : 6.0,
    "win" : 1.0,
    "lost" : 4.0,
    "draw" : 1.0,
    "goalsFor" : 7.0,
    "goalsAgainst" : 12.0,
    "goalDifferential" : 5.0,
    "points" : 4.0
}

/* 17 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c1c"),
    "played" : 5.0,
    "win" : 0.0,
    "lost" : 3.0,
    "draw" : 2.0,
    "goalsFor" : 2.0,
    "goalsAgainst" : 13.0,
    "goalDifferential" : 11.0,
    "points" : 2.0
}

/* 18 */
{
    "_id" : ObjectId("596fe03ad496e047d6314c0d"),
    "played" : 3.0,
    "win" : 0.0,
    "lost" : 2.0,
    "draw" : 1.0,
    "goalsFor" : 1.0,
    "goalsAgainst" : 4.0,
    "goalDifferential" : 3.0,
    "points" : 1.0
}

当然,如果您想要“团队名称”,那么显然它位于“另一个集合”中,您将使用$lookup 和进一步操作以将适当的ObjectId 值与其他相关集合匹配您在最终输出中想要的信息。

【讨论】:

  • 感谢您的回复 Neil,我尝试从 Robo 3T 执行您的查询,但出现以下错误。 Assert: command failed: { "ok" : 0, "errmsg" : "field inclusion is not allowed inside of $expressions", "code" : 16420 } : aggregate failed _getErrorWithCode@src/mongo/shell/utils.js:25:13 doassert@src/mongo/shell/assert.js:16:14 assert.commandWorked@src/mongo/shell/assert.js:370:5 DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1319:5 @(shell):1:1
  • @blacktone 如果您注意我粘贴的输出(就像我对您的输入所做的那样),那么您会注意到我也通过 Robo3T 运行了整个过程而没有任何错误。您的 MongoDB 服务器版本是什么?它可能是$map 中的"played" 字段,您可以改为使用"played": { "$literal": 1 }。但是对我来说使用 MongoDB 3.4 可以正常工作,事实上,如果你的版本是 MongoDB 至少 3.2,你应该不需要改变任何东西。
  • 我正在使用托管的 mLab 数据库。他们使用 3.2。但是你说它仍然不应该是一个问题,所以我不知道我在这里做错了什么。感谢您的帮助。
  • @blacktone 你真的应该能够简单地复制和粘贴这里的内容。就像我说的那样,我只是在问题中复制了您的数据并放入名为"games" 的集合中,如图所示。我可以检查一个 3.2 实例来确定,但是这里没有什么会产生那个特定的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多