Javascript 使用JS按时间窗口进行数据聚合
我构建了一个简单的NodeJS服务器,它发出客户端事件。事件是一个JSON对象,如下所示: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”, “事件”:“某些事件” } 可以
{
"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分钟组。在同一秒内聚合所有事件将无法正常工作。@这是不真实的。只需为每个事件对象caleddat添加一个键即可eSlot
或其他东西,并将时间戳四舍五入。然后,您可以按此处所述使用groupBy或reduce。@TheUnreal哦,是的,它适用于您的用例。您可以使用此实用工具进行检查。这允许您评估所提供的间隔。但是,请注意,您可能需要在常规间隔内提取事件al使用一些预定函数,然后更新groupBy函数,检查k==“date”
是否进行预处理,以确定您只需要预定义间隔内的事件,或者只需遵循@Imre\G的建议