MongoDB:汇总具有时间范围阈值的数据

时间:2018-07-31 14:37:28

标签: arrays mongodb statistics aggregation-framework analytics

我的数据看起来像这样:

{
  "timestamp": ISODate("2018-07-31T13:30:00Z"),
  "mapId": "b312c970-ea39-436d-b930-47ce64ff910f",
  "deviceId": "e272f2be-b398-4489-afa4-cb1a249406bf",
  "_id": ObjectId(...)
}

我们假设它们是地图上的位置(被截断的数据)。

我想在MongoDB中执行以下语句。

  

查找任何设备在特定地图上花费的平均时间。如果两个连续的差值大于特定阈值,则设备将离开地图。

一个例子,我们假设只存在一张地图。请注意,我们对每个特定设备的平均时间不感兴趣,而对所有设备的平均时间感兴趣。 (因此,数据中只提到了时间戳记)

[
  { "timestamp": ISODate("2018-07-31T13:30:00Z") },
  { "timestamp": ISODate("2018-07-31T13:40:00Z") },
  { "timestamp": ISODate("2018-07-31T13:55:00Z") },
  { "timestamp": ISODate("2018-07-31T15:40:00Z") },
  { "timestamp": ISODate("2018-07-31T15:45:00Z") },
  { "timestamp": ISODate("2018-07-31T18:00:00Z") },
]

我们将定义离开设备的时差设置为15分钟。据此,我们将得到15 minutes的平均花费时间。为什么会这样?

  • 前三个条目(时间13:30到13:55)都在15分钟阈值之内
  • 第4个和第5个条目也可以分组
  • 最后一个时间戳将被忽略,因为在15分钟阈值之内没有上一个或下一个时间戳

因此,我们有两个25 minutes, 5 minutes的跨度。计算平均值:(25 + 5) minutes / 2 timespans = 15 minutes

使用普通JavaScript,我将执行以下操作(我不想讨论代码的质量-我知道它可以提高。:))

const threshold = 1000 * 60 * 15;
const timespans = [];
let previous = undefined;
let valuesWithinThreshold = [];

dataForOneDevice
  .sort((a, b) => a.timestamp < b.timestamp ? -1 : 1)
  .forEach((position, index) => {
    if (index === 0) {
      valuesWithinThreshold.push(position);
    }

    if (previous) {
      const range = Math.abs(previous.timestamp - position.timestamp);

      if (range <= threshold) {
        valuesWithinThreshold.push(position);
      } else {
        const first = valuesWithinThreshold[0];
        const last = valuesWithinThreshold[valuesWithinThreshold.length - 1];
        if (first && last && first !== last) {
          timespans.push(last.timestamp - first.timestamp);
        }
        valuesWithinThreshold = [];
        valuesWithinThreshold.push(position);
      }
    }
    previous = position;
  });

const sum = timespans.reduce((a, b) => a + b);
console.log('average', sum / timespans.length / 1000 / 60, 'minutes');

我的问题

  1. 是否可以通过单个mongo聚合来实现?尤其是遍历数组并访问先前值的部分-在MongoDB中是否还可以实现?
  2. 如果我存储其他数据,例如新创建的数据条目的先前位置(根据时间),会变得更容易吗?

最好, 菲利普

0 个答案:

没有答案