【问题标题】:keep latest record based on multiple grouping保持基于多个分组的最新记录
【发布时间】:2020-07-20 14:43:41
【问题描述】:

我写了一个多阶段的管道来得到这组文档:

{'_id': '1234'),
  'info': [{'type': 'patient',
    'patient_id': 'p1'},
   {'type': 'doc',
    'doc_id': 'd1'},
   {'type': 'ldlc',
    'dt': datetime.datetime(2018, 10, 29, 12, 7, 23),
    'val': 136},
   {'type': 'bp',
    'dt': datetime.datetime(2014, 8, 25, 4, 2, 27),
    'val': [{'dias': 74}, {'sys': 105}]}]},
{'_id': '1235'),
  'info': [{'type': 'patient',
    'patient_id': 'p2'},
   {'type': 'doc',
    'doc_id': 'd1'},
   {'type': 'ldlc',
    'dt': datetime.datetime(2016, 3, 31, 21, 30, 34),
    'val': 153},
   {'type': 'bp',
    'dt': datetime.datetime(2013, 7, 3, 18, 3, 12),
    'val': [{'dias': 86}, {'sys': 101}]},
   {'type': 'bp',
    'dt': datetime.datetime(2016, 3, 15, 18, 35, 25),
    'val': [{'dias': 85}, {'sys': 108}]},
   {'type': 'ldlc',
    'dt': datetime.datetime(2018, 10, 1, 12, 7, 23),
    'val': 144}]}

我使用的是 pymongo,因此使用的是 datetime 对象。

现在,在每个文档中,我只想保留 'ldlc' 和 'bp' 的最后记录值(按 dt 排序)。

我希望它是:

{
  "_id": '1234',
  "patient_id": "p1",
  "doc_id": "d1".
  "sys": 105,
  "dias": 74,
  "ldlc": 136

},
{
  "_id": '1235',
  "patient_id": "p2",
  "doc_id": "d1".
  "sys": 108,
  "dias": 85,
  "ldlc": 144
}

由于源文档是在聚合管道中生成的,因此我想在此之后添加 $project 和 $group 阶段以产生所需的结果。

感谢您的帮助!

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    有不同的方法来实现这个用例。

    我从$sort 开始根据日期进行排序。然后使用$facet进行并行分组。由于只需要保留最新的记录,因此$last用于获取所需的值。

    您的聚合可能如下所示:

    db.collection.aggregate([
      {
        $unwind: "$info"
      },
      {
        $sort: {
          "info.dt": 1
        }
      },
      {
        "$facet": {
          "ldlc": [
            {
              "$match": {
                "info.type": "ldlc"
              }
            },
            {
              "$group": {
                "_id": "$_id",
                "ldlc": {
                  $last: "$info.val"
                }
              }
            }
          ],
          "bp": [
            {
              "$match": {
                "info.type": "bp"
              }
            },
            {
              "$group": {
                "_id": "$_id",
                "bp": {
                  $last: "$info.val"
                }
              }
            },
            {
              $unwind: "$bp"
            }
          ],
          "others": [
            {
              $match: {
                $or: [
                  {
                    "info.type": "patient"
                  },
                  {
                    "info.type": "doc"
                  }
                ]
              }
            },
            {
              "$group": {
                "_id": "$_id",
                "ids": {
                  $push: {
                    p: "$info.patient_id",
                    d: "$info.doc_id"
                  }
                }
              }
            },
            {
              $unwind: "$ids"
            }
          ],
          
        }
      },
      {
        $project: {
          data: {
            $concatArrays: [
              "$others",
              "$ldlc",
              "$bp"
            ]
          }
        }
      },
      {
        $unwind: "$data"
      },
      {
        "$group": {
          "_id": "$data._id",
          "val": {
            $push: {
              patient_id: "$data.ids.p",
              doc_id: "$data.ids.d",
              ldlc: "$data.ldlc",
              dias: "$data.bp.dias",
              sys: "$data.bp.sys"
            }
          }
        }
      },
      {
        "$project": {
          _id: 1,
          "v": {
            "$reduce": {
              "input": "$val",
              "initialValue": {},
              "in": {
                "$mergeObjects": [
                  "$$value",
                  "$$this"
                ]
              }
            }
          }
        }
      },
      {
        "$project": {
          _id: 1,
          patient_id: "$v.patient_id",
          doc_id: "$v.doc_id",
          ldlc: "$v.ldlc",
          dias: "$v.dias",
          sys: "$v.sys"
        }
      }
    ])
    

    在这里查看查询结果:Mongo Playground

    PS:这可能不是最好的方法

    【讨论】:

    • 这太好了,非常感谢您抽出宝贵时间帮助我!
    猜你喜欢
    • 1970-01-01
    • 2021-04-28
    • 2016-12-09
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2011-08-31
    相关资源
    最近更新 更多