MongoDB 通过过滤条件查找多个最新的

问题描述 投票:0回答:1

想象以下示例数据:

[
  {
    "_id": 1,
    "category": "FIRE",
    "time": "2024-05-11T07:11:00Z"
  },
  {
    "_id": 2,
    "category": "FIRE",
    "time": "2024-05-11T08:11:00Z"
  },
  {
    "_id": 3,
    "category": "FIRE",
    "time": "2024-05-11T09:11:00Z"
  },
  {
    "_id": 4,
    "category": "POLICE",
    "time": "2024-05-11T07:22:00Z"
  },
  {
    "_id": 5,
    "category": "POLICE",
    "time": "2024-05-11T08:22:00Z"
  },
  {
    "_id": 6,
    "category": "POLICE",
    "time": "2024-05-11T09:22:00Z"
  },
  {
    "_id": 7,
    "category": "AMBULANCE",
    "time": "2024-05-11T07:33:00Z"
  },
  {
    "_id": 8,
    "category": "AMBULANCE",
    "time": "2024-05-11T08:33:00Z"
  },
  {
    "_id": 9,
    "category": "AMBULANCE",
    "time": "2024-05-11T09:33:00Z"
  }
]

对于一组类别(例如

["FIRE", "AMBULANCE"]
)和时间戳(例如
["2024-05-11T08:15:00Z", "2024-05-11T09:00:00Z"]
)中的每个组合,我想在每个类别的每个时间戳上或之前获取latest条目:

[
  {
    "category": "FIRE",
    "time": "2024-05-11T08:15:00Z",
    "last_entry_on_or_before": {
      "_id": 2,
      "category": "FIRE",
      "time": "2024-05-11T08:11:00Z"
    }
  },
  {
    "category": "FIRE",
    "time": "2024-05-11T09:00:00Z",
    "last_entry_on_or_before": {
      "_id": 2,
      "category": "FIRE",
      "time": "2024-05-11T08:11:00Z"
    }
  },
  {
    "category": "AMBULANCE",
    "time": "2024-05-11T08:15:00Z",
    "last_entry_on_or_before": {
      "_id": 7,
      "category": "AMBULANCE",
      "time": "2024-05-11T07:33:00Z"
    }
  },
  {
    "category": "AMBULANCE",
    "time": "2024-05-11T09:00:00Z",
    "last_entry_on_or_before": {
      "_id": 8,
      "category": "AMBULANCE",
      "time": "2024-05-11T08:33:00Z"
    }
  }
]

这可以在单个高效聚合管道中完成吗?我在

[category, time]
上有一个复合索引。

mongodb mongodb-query
1个回答
0
投票

您可以使用

$documents
来生成数组与
$unwind
的组合。然后,只需执行
$lookup
即可找到匹配的记录,然后将
$sort
$limit
链接起来即可获取最新记录。

db.aggregate([
  {
    "$documents": [
      {
        "category": //your input category array here
        [
          "FIRE",
          "AMBULANCE"
        ],
        //your input time array here
        "time": [
          "2024-05-11T08:15:00Z",
          "2024-05-11T09:00:00Z"
        ]
      }
    ]
  },
  {
    "$unwind": "$category"
  },
  {
    "$unwind": "$time"
  },
  {
    "$lookup": {
      "from": "collection",
      "localField": "category",
      "foreignField": "category",
      "let": {
        ts: "$time"
      },
      "pipeline": [
        {
          "$match": {
            $expr: {
              $lte: [
                "$time",
                "$$ts"
              ]
            }
          }
        },
        {
          "$sort": {
            "time": -1
          }
        },
        {
          "$limit": 1
        }
      ],
      "as": "last_entry_on_or_before"
    }
  },
  {
    "$unwind": "$last_entry_on_or_before"
  }
])

蒙戈游乐场

playground 中的语法略有不同,因为

$documents
不允许直接在 Playground 中使用,需要解决这个问题。对于您实际的 mongo shell/其他驱动程序,上述语法应该有效。

© www.soinside.com 2019 - 2024. All rights reserved.