Elasticsearch复杂的多存储桶时间聚合-会话数据到用户计数

时间:2019-02-14 21:56:42

标签: elasticsearch kibana

具有这样的用户会话数据集:

{'username':'TestUser',
 'sessionStartTime' : '2019-02-14 09:00:00'
 'sessionEndTime' : ''2019-02-14 10:20:00'},
{'username':'User2',
 'sessionStartTime' : '2019-02-14 02:00:00'
 'sessionEndTime' : ''2019-02-14 12:00:00'}

是否有一种简单的方法来查询弹性以获取时间范围内会话的多存储桶总和?

所以基本上我想查询时间范围09:00:00到11:00:00并得到这样的每小时汇总结果:

{'bucketStart' : '2019-02-14 09:00:00',
'bucketEnd' : '2019-02-14 10:00:00',
'sessioncount' : 2},
{'bucketStart' : '2019-02-14 10:00:00',
'bucketEnd' : '2019-02-14 11:00:00',
'sessioncount' : 1}

这样做的目的是,使用结果数据为“在线”用户会话计数绘制折线图,​​而数据库中仅包含会话数据。

2 个答案:

答案 0 :(得分:1)

好吧,我是在日期(每天)上进行此设置的,因此请调整360000 * 24(date_histogram间隔中的毫秒数,对我来说是天)。

您可能要做的第二件事是将日期缩短为小时(我的意思是14:03 => 14:00、12:37 => 12h等...,四舍五入为结束时间,四舍五入为开始时间时间)

我不是专业人士,所以我将agg结果存储在预定义的数组(大小为99)中,也许我们可以使用动态列表来实现。无论如何,如果您的会话时间可能超过99小时,请进行调整。

该脚本创建一个agg by day数组,将日期按小时分割。

{
    "query": {
         // your filter query
    },
    "aggs": {
    "active_alerts": {
      "date_histogram": {
        "interval": "day",
        "script": {
            "inline": "def currentDate=(doc['sessionStartTime'].value); def endDate=(doc['sessionEndTime'].value); def combined=[99]; def counter = 0; while ((currentDate < endDate) && (counter < 99)) { combined[counter] = currentDate; currentDate += 3600000 * 24 } return combined",
            "lang":"painless"
        }
      }
    }
  }
}

希望有帮助,让我知道;)

答案 1 :(得分:0)

完整解决方案供参考:

此外,允许不存在“ to”的开放范围。

在Kibana中,将以下脚本添加到X系列日期直方图agg:

{"script": {
          "lang": "painless",
          "source": "
def currentDate=(doc['from'].value); 
def endDate=(doc['to']); 
def endDateValue = endDate.size() == 0 ? ZonedDateTime.ofInstant(Calendar.getInstance().toInstant(), ZoneOffset.UTC): endDate.value; 
def combined = new ArrayList(); 
while ((currentDate.isBefore(endDateValue))) { combined.add(currentDate); currentDate = currentDate.plusDays(1) } return combined"
        },
        "field": null,
        "calendar_interval": "1d"
} 

对于ES API agg:

GET /<index>/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "fromto_range":{
      "date_histogram" : {
        "script": {
          "lang": "painless",
          "source": "def currentDate=(doc['from'].value); def endDate=(doc['to']); def endDateValue = endDate.size() == 0 ? ZonedDateTime.ofInstant(Calendar.getInstance().toInstant(), ZoneOffset.UTC): endDate.value; def combined = new ArrayList(); while ((currentDate.isBefore(endDateValue))) { combined.add(currentDate); currentDate = currentDate.plusDays(1) } return combined"
          
        },
        "calendar_interval":"1d"
      }
    }
  }
}