查询一个mongodbtimeseries集合,获取数据点之间的时间差

fumotvh3  于 2023-03-29  发布在  Go
关注(0)|答案(1)|浏览(136)

假设我们有一个MongoDB时间序列集合,目前没有 meta字段。

const granularity = "second";
const expireAfterSeconds = 60 * 60 * 24 * 365;

createCollection("test", {
    timeseries: {
        timeField: "_createdAt",
        //metaField: "metadata",
        granularity,
    },
    expireAfterSeconds,
});

我们想知道所考虑的文档和前一个文档之间的时间。由于集合没有 meta字段,我们不能修改文档并在之后添加第二个时间戳。
我们可以运行以下聚合流水线:

collection("test").aggregate([
  {
    $sort: {
      _createdAt: 1
    }
  },
  {
    $lookup: {
      from: "test",
      let: { current_timestamp: "$_createdAt" },
      pipeline: [
        {
          $match: {
            $expr: {
              $or: [
                { $eq: ["$_createdAt", "$$current_timestamp"] },
                { $lt: ["$_createdAt", "$$current_timestamp"] }
              ]
            }
          }
        },
        {
          $sort: {
            _createdAt: -1
          }
        },
        {
          $limit: 2
        }
      ],
      as: "matched_docs"
    }
  },
  {
    $addFields: {
      prev_doc: { $arrayElemAt: ["$matched_docs", 1] },
    }
  },
  {
    $addFields: {
      _deltaTms: {
        $subtract: ["$_createdAt", "$prev_doc._createdAt"]
      },
    }
  },
  {
    $project: {
      matched_docs: 0,
      prev_doc: 0,
    }
  }
]).toArray();

此解决方案使用_deltaTms字段扩展文档,该字段是最后一个文档之间的时间增量(以毫秒为单位)。
我想知道这是否是正确的解决方案,它看起来有点过于复杂。在查询速度方面,添加一个 meta字段是否更有效,而不是通过添加时间戳和使用元字段来修改最后一个文档?

piztneat

piztneat1#

从mongodb版本5.0开始,你可以使用$setWindowFields来实现:

db.collection.aggregate([
  {$setWindowFields: {
      sortBy: {_createdAt: 1},
      output: {prev: {
          $first: "$_createdAt",
          window: {documents: [-1, 0]}
      }}
  }},
  {$set: {
      _deltaTms: {$subtract: ["$_createdAt", "$prev"]},
      prev: "$$REMOVE"
  }}
])

了解它在playground example上的工作原理

相关问题