仅汇总最新文档

时间:2016-11-13 04:45:41

标签: elasticsearch elasticsearch-aggregation

我有一个弹性索引,其中包含用户状态历史记录。数据看起来像这样;

  {
    "session_id": "yunus",
    "state_name": "start",
    "entry_time": "2016-11-09 15:27:03"
  },
  {
    "session_id": "yunus",
    "state_name": "end",
    "entry_time": "2016-11-09 16:30:00"
  },
  {
    "session_id": "can",
    "state_name": "start",
    "entry_time": "2016-11-09 12:01:00"
  },
  {
    "session_id": "rick",
    "state_name": "start",
    "entry_time": "2016-11-09 09:00:00"
  },
  {
    "session_id": "rick",
    "state_name": "end",
    "entry_time": "2016-11-10 10:00:00"
  }

我希望通过状态名称与日期直方图进行聚合,但仅限于当时相关的最后状态。结果可以是;

2016-11-08 
start = 0
end = 0

2016-11-09 
start = 2
end = 1

2016-11-10 
start = 1
end = 2

实际上,计划是生成带有时间轴的分组条形图,以显示状态随时间的变化。

我尝试过聚合管道,热门点击等几件事,但无法取得任何进展。

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:0)

对于任何有兴趣的人,我用火花解决了它。我使用elastic-spark从elasticsearch读取,然后回写给elasticsearch。

以下是es的{​​{1}};

Rdd

然后我首先按会话ID分组,按日期排序以仅查找会话的最新状态;

val allData = sc.esRDD(s"states_${id}/log", query)

一旦我有最新的会话状态,我会过滤退出状态,然后按值计算;

val latestStates = allData.groupBy(k => k._2.get("session_id").get).map(k => (k._2).reduceLeft((d1, d2) => {
  d1._2.get("timestamp").get.asInstanceOf[Long] > d2._2.get("timestamp").get.asInstanceOf[Long] match {
    case true => d1
    case false => d2
  }
})).map(_._2)

现在,我们拥有各州的当前会话数。 (当前是可配置的,所以我们可以在特定的时间设置它),只留下一些东西,回写给elasticsearch;

val stateSummary = latestStates
  .filter(s => s.isDefinedAt("state_id") && s("state_id").asInstanceOf[Long] != -1)
  .map(s => (s("state_id"), s("state_name")))
  .countByValue()
  .map(d => Map("state_id" -> d._1._1.asInstanceOf[Long], "state_name" -> d._1._2.asInstanceOf[String], "count" -> d._2)).toList