使用JS按时间窗口进行数据聚合

我构建了一个简单的NodeJS服务器,该服务器发出客户端事件。事件是一个如下所示的JSON对象:

{
  "date": "2019-12-12T09:55:05.679Z","clientId": "Client01","ip": "10.1.1.1","event": "someEvent"
}

可以随时发出事件。我收到许多带有不同时间戳记(date)的消息。

当前,我将所有数据存储在内存中。

如何按日期汇总客户端事件?

让我们以15分钟的时间为例,因此我得出每个时间段的客户端事件总数,例如:

const timestamps = ["2019-12-12T09:00:00.000Z","2019-12-12T09:15:00.000Z","2019-12-12T09:30:00.000Z"];
const totalNumEvents = [50,27,82];
const clientIds = ["Client01","Client02","Client03"];

很抱歉,如果这个问题太笼统,我试图通过谷歌搜索寻找方向,但是如果不使用像MongoDB这样的框架/数据库就找不到任何解决方案。

到目前为止,我所做的是为每个clientId创建一个对象并将事件推送到其中。 (每个事件都有一个回调)

const onEventArrived = (client) => {
      if (!clients[client.clientId]) {
        console.log(`[New] Client Added - ${client.clientId}`);
        clients[client.clientId] = [{ date,client}];
      } else {
        console.log(`[Exist] New Client Message for ${client.clientId}`);
        clients[client.clientId].push({ date,client});
      }
});

回到问题上,我拥有每个客户端的所有事件,但是如何将随机时间汇总到固定的15分钟窗口中?

ert345 回答:使用JS按时间窗口进行数据聚合

您将需要将事件作为平面对象存储在数组中,并使用Array.reduce()或lodash的groupBy()将事件对象的数组按任何所需字段进行分组。

以下是使用您提供的事件示例的示例

您的传入事件如下:

{
  "date": "2019-12-12T09:55:05.679Z","clientId": "Client01","ip": "10.1.1.1","event": "someEvent"
}

现在,收到此事件后,将发生以下情况:

const events = []
const onEventArrived = (event) => {
     events = [...events,event ]
});

接下来,您将按以下方式运行组:

Array.prototype.groupBy = function(k) {
  return this.reduce((acc,item) => ((acc[item[k]] = [...(acc[item[k]] || []),item]),acc),{});
};

events.groupBy("date")
// OR
events.groupBy("clientId")

您可以扩展它以适合您的用例

参考:How to group an array of objects by key

,

一个主意可以是:

  • 将ID关联到每个日期(一个QuarterId)
  • 获取minQuarterId,maxQuarterId,并用0填充两者之间的值

const bulks = {}
const clientIds = new Set
function onev(ev) {
  clientIds.add(ev.clientId)
  const quarters = ev.date.getTime() / (15 * 60 * 1000)
  const quarterId = Math.floor(quarters)
  bulks[quarterId] = (bulks[quarterId] || 0) + 1
}

function restitute() {
  if(!Object.keys(bulks).length){ return { ts: [],nevs: [] } }
  const ts = []
  const nevs = []
  const {min,max} = Object.keys(bulks).reduce((acc,k) => {
    const pk = parseInt(k)
    if(pk < acc.min){
      acc.min = pk
    }
    if (pk > acc.max) {
      acc.max = pk
    }
    return acc
  },{min:1e15,max:0})
  for(let i = min; i <= max; ++i){
    ts.push(new Date(i * 15 * 60 * 1000))
    nevs.push(bulks[i] || 0) // fill with 0 if no quarterId "i" exists
  }
  return {ts,nevs}
}


onev({clientId: 1,date:new Date(2019,11,12,13,24)})
onev({clientId: 2,28)})
onev({clientId: 1,29,30)})
onev({clientId: 1,31,30),newquarter:1})
onev({clientId: 4,30)})
onev({clientId: 4,emptyquarters:1})
onev({clientId: 4,45,indapast:1})
console.log(restitute())

本文链接:https://www.f2er.com/2934522.html

大家都在问