将分组的结果合并到 Mongo 中的一个文档中

merge grouped results into one document in Mongo

我有一个这样的文档

  {
    "_id": {
      "$oid": "6187e5fa4ebcc2db6c86081f"
    },
    "publicId": "S23DCL",
    "flights": [
      {
        "name": "f1",
        "_id": {
          "$oid": "620026293fc350024da614dd"
        },
        "wines": [
          {
            "id": "1",
            "name": "wine1"
          },
          {
            "id": "2",
            "name": "wine2"
          }
        ]
      },
      {
        "name": "f2",
        "_id": {
          "$oid": "6200263c3fc350024da614de"
        },
        "wines": [
          {
            "id": "3",
            "name": "leVin"
          },
          {
            "id": "4",
            "name": "theWine"
          }
        ]
      }
    ],
    "title": "Pinot Noir 2022",
    "scores": [
      {
        "userId": "f8Dv",
        "userName": "gugus",
        "scores": [
          {
            "score": 95,
            "wineId": "1"
          },
          {
            "score": 88,
            "wineId": "2"
          }
        ]
      },
      {
        "userId": "yLjh",
        "userName": "test",
        "scores": [
          {
            "score": 92,
            "wineId": "1"
          },
          {
            "score": 87,
            "wineId": "2"
          }
        ]
      },
      {
        "userId": "B6em",
        "userName": "jklsdf",
        "scores": [
          {
            "score": 88,
            "wineId": "1"
          },
          {
            "score": 90,
            "wineId": "2"
          },
          {
            "score": 92,
            "wineId": "3"
          },
          {
            "score": 86,
            "wineId": "4"
          }
        ],
        "isFinished": false
      }
    ],
  }

如果问题太长我可以缩短它。
整个文档和查询也可以是found in mongoplayground

我想做的是为所有葡萄酒创建一个记分牌,这意味着为每种葡萄酒计算平均等,同时仍然只有一个文档。

像这样

{
  "title": "Pinot Noir 2022"
  "results": [
    {
       "wine": {
          "flightName": "f1",
           "wineIndex": 1,
           "name": "wine1",
           "wineId": "1"
        },
        "avg": 90,
        "scores": [
           {
        "scores": {
          "score": 87,
          "wineId": "1"
        },
        "userId": "yLjh",
        "userName": "test"
      },
        ] 
    }
   ]
}

我快完成了,但是我在分组后想要一个结果文档的部分遇到了困难。

scores中的wineId对应flights.wines

中的id

这是我目前所拥有的

db.collection.aggregate([
  {
    "$match": {
      "publicId": "S23DCL"
    }
  },
  {
    "$project": {
      "scores": "$scores",
      "publicId": "$publicId"
    }
  },
  {
    "$unwind": "$scores"
  },
  {
    "$unwind": "$scores.scores"
  },
  {
    $lookup: {
      from: "collection",
      let: {
        wId: "$scores.scores.wineId",
        "tastingId": "$_id"
      },
      pipeline: [
        {
          "$unwind": "$flights"
        },
        {
          "$unwind": {
            "path": "$flights.wines",
            "includeArrayIndex": "index"
          }
        },
        {
          $match: {
            $expr: {
              "$and": [
                {
                  "$eq": [
                    "$flights.wines.id",
                    "$$wId"
                  ]
                },
                {
                  "$eq": [
                    "$_id",
                    "$$tastingId"
                  ]
                }
              ]
            },
            
          }
        },
        {
          $project: {
            _id: 0,
            "name": "$flights.wines.name",
            "flight": "$flights.name",
            "wineId": "$flights.wines.id",
            "index": "$index"
          }
        }
      ],
      as: "wine"
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          {
            "_id": "$_id",
            "scores": "$scores"
          },
          {
            "wine": {
              "$arrayElemAt": [
                "$wine",
                0
              ]
            }
          }
        ]
      }
    }
  },
  {
    "$group": {
      "_id": "$wine",
      "avg": {
        "$avg": "$scores.scores.score"
      },
      "min": {
        "$min": "$scores.scores.score"
      },
      "max": {
        "$max": "$scores.scores.score"
      },
      "stddev": {
        "$stdDevPop": "$scores.scores.score"
      },
      "tmp": {
        "$max": 1
      },
      "scores": {
        "$addToSet": "$scores"
      }
    }
  }
])

这给了我上面 results 中看到的数据。但是缺少像“标题”这样的数据。
请注意 tmp 字段。我试图在后期添加这个虚拟字段并对其进行分组。
因为总是只有一组(因为 tmp 是静态的)。
喜欢

// query from abive
,{
 "$group": {
  "$_id": "tmp"
  // add my grouped results from before into an array
}
}

那么如何将分组结果添加到一个数组中,这样我就不会返回 (n) 个组,而是得到分组结果在数组中的一个文档?

希望你明白我的意思:)

也许是这样的:

 {
  $group: {
  _id: "tmp",
   array: {
    $push: "$$ROOT"
   }
  }
}

playground

当您使用 replaceRoot 替换根目录时,您的标题丢失了。首先,您必须将它添加到新的根级别。 这个 returns 你的标题 .

[
  {
    '$match': {
      'publicId': 'S23DCL'
    }
  }, {
    '$project': {
      'scores': '$scores', 
      'publicId': '$publicId', 
      'title': '$title', 
      'flights': '$flights'
    }
  }, {
    '$unwind': '$scores'
  }, {
    '$unwind': '$scores.scores'
  }, {
    '$lookup': {
      'from': 'collection', 
      'let': {
        'wId': '$scores.scores.wineId', 
        'tastingId': '$_id'
      }, 
      'pipeline': [
        {
          '$unwind': '$flights'
        }, {
          '$unwind': {
            'path': '$flights.wines', 
            'includeArrayIndex': 'index'
          }
        }, {
          '$match': {
            '$expr': {
              '$and': [
                {
                  '$eq': [
                    '$flights.wines.id', '$$wId'
                  ]
                }, {
                  '$eq': [
                    '$_id', '$$tastingId'
                  ]
                }
              ]
            }
          }
        }, {
          '$project': {
            '_id': 0, 
            'name': '$flights.wines.name', 
            'flight': '$flights.name', 
            'wineId': '$flights.wines.id', 
            'index': '$index'
          }
        }
      ], 
      'as': 'wine'
    }
  }, {
    '$addFields': {
      'scores.title': '$title'
    }
  }, {
    '$replaceRoot': {
      'newRoot': {
        '$mergeObjects': [
          {
            '_id': '$_id', 
            'scores': '$scores'
          }, {
            'wine': {
              '$arrayElemAt': [
                '$wine', 0
              ]
            }
          }
        ]
      }
    }
  }, {
    '$group': {
      '_id': '$wine', 
      'title': {
        '$last': '$scores.title'
      }, 
      'avg': {
        '$avg': '$scores.scores.score'
      }, 
      'min': {
        '$min': '$scores.scores.score'
      }, 
      'max': {
        '$max': '$scores.scores.score'
      }, 
      'stddev': {
        '$stdDevPop': '$scores.scores.score'
      }, 
      'tmp': {
        '$max': 1
      }, 
      'scores': {
        '$addToSet': '$scores'
      }
    }
  }
]

但是您当前的聚合管道有太多阶段。如果您解释一下您的数据源究竟需要什么,它可能需要稍微优化一下