循环操作后如何访问不同集合中的嵌入字段?

How do i access a embedded field from different collection after loopup operation?

我收集了 4 个球员统计数据: Laliga2017、Laliga2018、Laliga2019和Laliga2020

{
    '_id': ObjectId('61eda25219e7e44801799d71'),
    'name': 'Sergio Ramos',
    'age': 34,
    'nationality': 'Spain',
    'height': 184,
    'weight': 82,
    'team': 'Real Madrid',
    'position': 'DF',
    'general_stats': {
        'games': 15,
        'time': 1280,
        'red_cards': 0,
        'yellow_cards': 3,
    },
    'offensive_stats': {
        'goals': 2,
        'xG': 3.95,
        'assists': 0,
        'xA': 0.4,
        'shots': 17,
        'key_passes': 4,
        'npg': 0,
        'npxG': 2.46,
        'xGChain': 9.06,
        'xGBuildup': 7.22,
    },
    'defensive_stats': {
        'Tkl': 20,
        'TklW': 12,
        'Past': 8,
        'Press': 97,
        'Succ': 39,
        'Blocks': 18,
        'Int': 16,
    },
    'passing_stats': {
        'Cmp': 1023,
        'Cmp%': 91.8,
        '1/3': 106,
        'PPA': 2,
        'CrsPA': 1,
        'Prog': 61,
    },
}

有没有办法得到所有 4 年的所有 goal_contribution(进球+助攻)的总和(对于每一年,然后是所有年份统计数据的总和)?

我到达这里:

db.LaLiga_2020.aggregate(
    [

        { $match: { name: 'Lionel Messi' } },
        {
            $lookup: {
                from: 'LaLiga_2019',
                localField: 'name',
                foreignField: 'name',
                as: 'stats2019',
            },
        },
        {
            $lookup: {
                from: 'LaLiga_2018',
                localField: 'name',
                foreignField: 'name',
                as: 'stats2018',
            },
        },
        {
            $lookup: {
                from: 'LaLiga_2017',
                localField: 'name',
                foreignField: 'name',
                as: 'stats2017',
            },
        },
        {
            $project: {
                _id: 0,
                name: 1,
                team: 1,
                position: 1,
                goal_cotribution_2020: { $add: ['$offensive_stats.goals', '$offensive_stats.assists'] },
                goal_cotribution_2019: { $sum: ['$stats2019.offensive_stats.goals', '$stats2019.offensive_stats.assists'] },
                goal_cotribution_2018: { $sum: ['$stats2018.offensive_stats.goals', '$stats2018.offensive_stats.assists'] },
                goal_cotribution_2017: { $sum: ['$stats2017.offensive_stats.goals', '$stats2017.offensive_stats.assists'] },
            },
        },
    ],
).pretty();

但是 returns:

{
    'name': 'Lionel Messi',
    'team': 'Barcelona',
    'position': 'FW',
    'goal_cotribution_2020': 39,
    'goal_cotribution_2019': 0,
    'goal_cotribution_2018': 0,
    'goal_cotribution_2017': 0,
};

问题出在你的 $project 阶段,特别是你 $sum:

goal_cotribution_2018: {
  $sum: [
    "$stats2018.offensive_stats.goals",
    "$stats2018.offensive_stats.assists"
  ]
}

问题是stats2018$lookup阶段之后的数组。所以 "$stats2018.offensive_stats.goals" 解析为数字数组而不是数字,想象一下你在做什么:

goal_cotribution_2018: {
  $sum: [
    [12],
    [5]
  ]
}

所以虽然没有抛出错误,但这是未定义的行为,$sum 只是 returns 0.

您可以通过几种不同的方式解决这个问题。你可以 $unwind 或使用 $arrayElemAt,但我认为“最干净”的方法只是添加一个额外的嵌套 $sum,像这样:

goal_cotribution_2018: {
  $sum: [
   {
     $sum: "$stats2019.offensive_stats.goals"
   },
   {
     $sum: "$stats2019.offensive_stats.assists"
   },
  ]
},

最简单的方法是在末尾添加所有字段应该可行

{
   "$project":{
      "_id":0,
      "name":1,
      "team":1,
      "position":1,
      "goal_cotribution_2020":{
         "$add":[
            "$offensive_stats.goals",
            "$offensive_stats.assists"
         ]
      },
      "goal_cotribution_2019":{
         "$add":[
            "$stats2019.offensive_stats.goals",
            "$stats2019.offensive_stats.assists"
         ]
      },
      "goal_cotribution_2018":{
         "$add":[
            "$stats2018.offensive_stats.goals",
            "$stats2018.offensive_stats.assists"
         ]
      },
      "goal_cotribution_2017":{
         "$add":[
            "$stats2017.offensive_stats.goals",
            "$stats2017.offensive_stats.assists"
         ]
      },
      "total_goal_cotribution":{
         "$add":[
            "$offensive_stats.goals",
            "$offensive_stats.assists",
            "$stats2019.offensive_stats.goals",
            "$stats2019.offensive_stats.assists",
            "$stats2018.offensive_stats.goals",
            "$stats2018.offensive_stats.assists",
            "$stats2017.offensive_stats.goals",
            "$stats2017.offensive_stats.assists"
         ]
      }
   }
}