【问题标题】:get the fields in the input document after $group in aggregation pipeline in MongoDB在 MongoDB 的聚合管道中获取 $group 之后的输入文档中的字段
【发布时间】:2015-05-12 19:24:55
【问题描述】:

我面临的问题是如何在一次分组操作后访问原始文档,以及如何在MongoDB的聚合管道中携带$group之后的字段。

例如:[group, unwind, group]

原始文件是:

{
"_id" : ObjectId("361de42f1938e89b179dda42"),
"user_id" : ObjectId("9424021bafbde55512e39b83"),
"candidate_id" : ObjectId("54f65356294160421ead3ca1")
"OVERALL_SCORE" : 150,
"SCORES" : [ 
    { "NAME" : "asd", "OBTAINED_SCORE" : 28}, { "NAME" : "acd", "OBTAINED_SCORE" : 36 }, { "NAME" : "abc", "OBTAINED_SCORE" : 40}
 ]
}

聚合函数:

 db.coll.aggregate([ $group : { _id : { user_id : "$user_id"}, BEST_SCORE : { $max : "$OVERALL_SCORE"}, AVG_SCORE : { $avg : "$OVERALL_SCORE" }}} ])

以下是示例输出(第一组之后):

{
"result" : [ 
    {
        "_id" : {
            "user_id" : ObjectId("9424021bafbde55512e39b83")
        },
        "BEST_SCORE" : 150,
        "AVG_SCORE" : 132
    }
],
"ok" : 1
 }

问题是:(不知道能不能实现) 我想要原始文档中的字段(聚合的输入)。

例如: 1) 通过“candidate_id”、“user_id”展开原始文档和下一组中的“SCORES”。

2) 我希望“BEST_SCORE”、“AVG_SCORE”(在第一组之后)字段也可以在第二组中访问。

聚合函数应该是这样的:

   db.coll.aggregate([ $group : { _id : { user_id : "$user_id"}, BEST_SCORE : { $max : "$OVERALL_SCORE"}, AVG_SCORE : { $avg : "$OVERALL_SCORE" }}}, { $unwind : "$SCORES"}, /*problem is--after group operation "SCORES" field which is in original document not available */ { $group : _id : { NAME: "$SCORES.NAME"}, AVG_OBTAINED_SCORE: { $avg : "$SCORES.OBTAINED_SCORE"}} **/*problem is--this is also in the original document*/** ])

输出应如下所示:

   "BEST_SCORE": 150,                     //after 1st group
  "AVG_SCORE": 132,                       //after 1st group
  "SCORES": [                             //problem --- unwind "SCORES" and then group which is actually will not be available after 1st group (get this from original document)
    {
      "NAME": "abc",
      "AVG_OBTAINED_SCORE": 25.5
    },
    {
      "NAME": "asd",
      "AVG_OBTAINED_SCORE": 24
    },
    {
      "NAME": "acd",
      "AVG_OBTAINED_SCORE": 32
    }
  ]

谁能帮帮我。

谢谢

【问题讨论】:

  • 这并没有多大意义。您只能真正“保留”“分组键”中的内容,否则可以由分组运算符之一保留,就像您使用其他值或可选的 $last 或 $push 之类的东西一样。保留其他字段的意义何在?您对最终结果的期望是什么。
  • $$ROOT 仅指调用它的聚合阶段的“整个文档”。因此,一旦您在一个阶段更改了文档,那么$$ROOT 的值就是在另一个阶段访问时更改的形式。您无法看到文档在进行其他更改之前的样子。正如我之前建议的那样,您的预期结果并不是很清楚。如果您编辑您的问题以显示您的期望,那么人们可能会就实现目标的方法提出建议。
  • 我已经编辑了..希望现在更清楚..
  • 你在 "name": "asd" 应该来自的地方失去了我们。除非它是“SCORES”数组文档的一部分,否则你很可能在这里不走运。它真的是那些数组文档中的一个元素吗?
  • 我们不要聊天。这是一个是或不是的答案。否则,请更改您问题的详细信息以解释数据应该来自哪里

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

当与您希望保留组中所有考虑文档的值的内容进行分组时,您需要使用$push。抓住的是,这是一个数组。所以你处理$unwind 两次,并且还有两个$group 阶段:

db.coll.aggregate([
    {  "$group" : { 
        "_id": "$user_id", 
        "BEST_SCORE": { "$max": "$OVERALL_SCORE" },
        "AVG_SCORE": { "$avg": "$OVERALL_SCORE" },
        "SCORES": { "$push": "SCORES" }
    }}, 

    // SCORES in an array of arrays. Unwind twice
    { "$unwind": "$SCORES" },
    { "$unwind": "$SCORES" },

    // Group for averages on elements
    { "$group": {
        "_id": {
            "user_id": "$_id",
            "NAME": "$SCORES.name"
        },
        "BEST_SCORE": { "$first": "$BEST_SCORE" },
        "AVG_SCORE": { "$first": "$AVG_SCORE" }
        "AVG_OBTAINED_SCORE": { "$avg": "$SCORES.OBTAINED_SCORE" } 
    }},

    // Group to user_id
    { "$group": {
        "user_id": "$_id.user_id",
        "BEST_SCORE": { "$first": "$BEST_SCORE" },
        "AVG_SCORE": { "$first": "$AVG_SCORE" }
        "SCORES": { "$push": {
            "NAME": "$_id.NAME",
            "AVG_OBTAINED_SCORE": "$AVG_OBTAINED_SCORE"
        }}     
    }}
])

您可能想在第一个 $group 之前考虑使用 $unwind,但如果您这样做了,那么计算的平均值将受到正在“解绕”的数组中存在的元素数量的影响。所以这里的“双重$unwind”是一个必要的过程。

【讨论】:

  • 如果有任何字段要结转到下一个管道操作员,我们需要使用$push或$addToSet。
  • @user3805045 你需要做一些事情,但这些都适合这个用例。
  • $push 和 $addToSet 之间的主要区别在于 push 添加的元素保持其顺序(无论在前面的阶段是什么),而 $addToSet 则以无特定顺序添加元素:docs.mongodb.com/manual/reference/operator/aggregation/addToSet
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 2019-10-05
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多