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

Javascript 使用JS按时间窗口进行数据聚合,javascript,node.js,aggregate,Javascript,Node.js,Aggregate,我构建了一个简单的NodeJS服务器,它发出客户端事件。事件是一个JSON对象,如下所示: { "date": "2019-12-12T09:55:05.679Z", "clientId": "Client01", "ip": "10.1.1.1", "event": "someEvent" } { “日期”:“2019-12-12T09:55:05.679Z”, “clientId”:“Client01”, “ip”:“10.1.1.1”, “事件”:“某些事件” } 可以

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

{
  "date": "2019-12-12T09:55:05.679Z",
  "clientId": "Client01",
  "ip": "10.1.1.1",
  "event": "someEvent"
}
{
“日期”:“2019-12-12T09:55:05.679Z”,
“clientId”:“Client01”,
“ip”:“10.1.1.1”,
“事件”:“某些事件”
}
可以随时发出事件。我收到许多带有不同时间戳的消息(
date

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

如何按日期聚合客户端事件?

假设以15分钟为单位,因此我最终得到每个时间段的客户端事件总数,例如:

const时间戳=[“2019-12-12T09:00:00.000Z”、“2019-12-12T09:15:00.000Z”、“2019-12-12T09:30:00.000Z”];
const totalNumEvents=[50,27,82];
常量clientId=[“Client01”、“Client02”、“Client03”];
很抱歉,如果这个问题太笼统,我试图通过谷歌搜索寻找方向,但如果不使用像MongoDB这样的框架/DB,就找不到任何解决方案

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


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

您需要将事件作为平面对象存储在数组中,并使用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")
您可以扩展它以适合您的用例

参考资料:

创意可以是:

  • 将id与每个日期关联(四分之一id)
  • 获取minquartId和maxquartId,并用0填充它们之间的值
constbulks={}
const clientId=新集合
功能onev(ev){
clientId.add(ev.clientId)
const quarters=ev.date.getTime()/(15*60*1000)
const quartID=数学楼层(四分之一)
散货[quarterId]=(散货[quarterId]| | 0)+1
}
函数恢复(){
if(!Object.keys(bulks.length){return{ts:[],nevs:[]}
常数ts=[]
常数nevs=[]
const{min,max}=Object.keys(bulks).reduce((acc,k)=>{
常数pk=parseInt(k)
如果(峰值<附件最小值){
acc.min=pk
}
如果(峰值>附件最大值){
acc.max=pk
}
返回acc
},{min:1e15,max:0})

对于(让i=min;i)这是一个模糊的问题。为什么不将对象推到数组中并使用reduce?如果某个季度没有事件会怎么样?您也不能自己实现它吗?而且,我假设您不发送带有日期的事件(比如过去的季度),是否正确?@Imre_G我已将对象推入每个客户端Id的数组中。您将如何使用reduce按时间聚合它?@grodzi如果我没有事件,则客户端Id的计数器在时间段应仅为0(或者如果根本没有事件,我不知道它存在)这不是我的情况,您的解决方案将为每个日期创建一个不同的组,并且我可以每秒获得一个新事件。我希望在特定的时间窗口内聚合所有事件,在我的情况下是15分钟组。在同一秒内聚合所有事件将无法正常工作。@这是不真实的。只需为每个事件对象caled
dat添加一个键即可eSlot
或其他东西,并将时间戳四舍五入。然后,您可以按此处所述使用groupBy或reduce。@TheUnreal哦,是的,它适用于您的用例。您可以使用此实用工具进行检查。这允许您评估所提供的间隔。但是,请注意,您可能需要在常规间隔内提取事件al使用一些预定函数,然后更新groupBy函数,检查
k==“date”
是否进行预处理,以确定您只需要预定义间隔内的事件,或者只需遵循@Imre\G的建议