You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB中查询按时间倒序后开头连续相同Port ID的条目

MongoDB 实现该需求的两种方案

注意将代码中的集合名ship_port替换为你实际使用的集合名称。

方案一:MongoDB 5.0+ 单聚合查询(推荐)

使用MongoDB 5.0推出的$setWindowFields窗口函数,一次聚合即可得到结果,管道代码如下:

db.ship_port.aggregate([
  // 第一步:按时间戳倒序全量排序
  { $sort: { timestamp: -1 } },
  // 第二步:给每行打分组标记,连续相同port_id为同一组
  {
    $setWindowFields: {
      sortBy: { timestamp: -1 },
      output: {
        group_flag: {
          $sum: {
            $cond: [
              { $eq: ["$port_id", { $lag: "$port_id", default: null }] },
              0,
              1
            ]
          },
          window: { documents: ["unbounded", "current"] }
        }
      }
    }
  },
  // 第三步:只取第一组(开头连续相同port_id的条目)
  { $match: { group_flag: 0 } },
  // 可选:去掉多余的group_flag字段
  { $unset: "group_flag" }
])

逻辑说明:排序后逐行对比当前行和上一行的port_id,第一次出现不同时group_flag会变为1,所有group_flag=0的条目就是开头连续相同port_id的结果。

方案二:兼容低版本MongoDB的两次查询方案

如果MongoDB版本低于5.0,没有窗口函数支持,可以用两次简单查询实现,性能同样很高:

  1. 先查询最新的一条记录,拿到目标port_id
const latestRecord = db.ship_port.findOne({}, { sort: { timestamp: -1 } });
const targetPortId = latestRecord.port_id;
  1. 再查询最新的、port_id不等于目标值的记录,拿到它的时间戳
const firstDiffRecord = db.ship_port.findOne(
  { port_id: { $ne: targetPortId } },
  { sort: { timestamp: -1 } }
);
  1. 最后查询所有时间戳大于第一个不同记录时间戳的条目,就是需要的结果
let result;
if (!firstDiffRecord) {
  // 所有记录port_id都相同,返回全部
  result = db.ship_port.find({}).sort({ timestamp: -1 }).toArray();
} else {
  result = db.ship_port.find({
    timestamp: { $gt: firstDiffRecord.timestamp }
  }).sort({ timestamp: -1 }).toArray();
}

性能优化建议

给timestamp字段建倒序索引,两种方案的查询效率都会达到最优,即使集合数据量很大也不会有性能问题。

内容的提问来源于stack exchange,提问作者Daniel Ramos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 17:15:03