Elasticsearch 日期聚合

标签 elasticsearch

我正在努力整理一个查询,需要一些帮助。文档很简单,只是记录了用户的登录时间

{
"timestamp":"2019-01-01 13:14:15",
"username":"theuser"
}

我希望根据今天(例如 10 天前)的偏移量使用以下规则进行计数。

  • 最近一次登录时间在 10 天前的用户将被视为“非活跃用户”
  • 任何在 10 天后首次登录的用户都被视为“新用户”
  • 任何其他用户都仅算作“活跃用户”。

我可以使用此方法获取每个用户的首次登录和最新登录(我发现这也可以通过 top_hits 聚合来完成)

GET mytest/_search?filter_path=**.buckets
{
    "aggs" : {
        "username_grouping" : {
            "terms" : {
                "field" : "username"
            },
            "aggs" : {
                "first_login" : {
                    "min": { "field" : "timestamp" }
                },
                "latest_login" : {
                    "max": { "field" : "timestamp" }
                }
            }
        }
    }
}

我正在考虑使用它作为日期范围聚合的源,但无法实现任何工作。

这是否可以在一个查询中实现,如果不可能,可以在单独的查询中计算“非事件用户”和“新用户”计数吗?

以下是一些示例数据,假设今天的日期是 2019 年 8 月 20 日,偏移量为 10 天,这将为每种类型的用户提供 1 的计数

PUT _template/mytest-index-template
{
  "index_patterns": [ "mytest" ],
  "mappings": {
    "properties": {
      "timestamp": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" },
      "username": { "type": "keyword" }
    }
  }
}

POST /mytest/_bulk
{"index":{}}
{"timestamp":"2019-01-01 13:14:15","username":"olduser"}
{"index":{}}
{"timestamp":"2019-01-20 18:55:05","username":"olduser"}
{"index":{}}
{"timestamp":"2019-01-31 09:33:19","username":"olduser"}
{"index":{}}
{"timestamp":"2019-08-16 08:02:43","username":"newuser"}
{"index":{}}
{"timestamp":"2019-08-18 07:31:34","username":"newuser"}
{"index":{}}
{"timestamp":"2019-03-01 09:02:54","username":"activeuser"}
{"index":{}}
{"timestamp":"2019-08-14 07:34:22","username":"activeuser"}
{"index":{}}
{"timestamp":"2019-08-19 06:09:08","username":"activeuser"}

提前致谢。

最佳答案

首先,提前抱歉。这将是一个很长的答案。

使用 Date Range Aggregation 怎么样? ?

您可以将“from”和“to”设置为特定字段并“标记”它们。这将帮助您确定谁是老用户和活跃用户。

我可以这样思考:

{
"aggs": {
    "range": {
        "date_range": {
            "field": "timestamp",
            "ranges": [
                { "to": "now-10/d", "key": "old_user" }, #If they have more than 10 days inactive.
                { "from": "now-10d/d", "to": "now/d", "key": "active_user" } #Ig they have at least logged in in the last 10 days.
            ],
            "keyed": true
        }
    }
}

第一个对象可以理解为:“所有字段‘timestamp’相差 10 天或以上的文档都将是 old_users”。在数学上表示为:

“from”(空值,我们可以称之为“-无限”)<=时间戳<“TO”10天前

第二个对象可以理解为:“所有字段‘timestamp’相差 10 天或更短的文档都将是 active_users”。在数学上表示为:

“FROM”10天前<=时间戳<“TO”现在

好的,我们已经找到了如何“标记”您的用户。但是如果您像这样运行查询,您会在结果中发现类似的内容:

user1: old_user
user1: old_user
user1: active_user
user2: old_user
user2: old_user
user2: active_user
user2: old_user
user3: old_user
user3: active_user

这是因为您将所有时间戳存储在一个索引中,并且它将在您的所有文档上运行。我假设您只想玩最后一个时间戳。您可以执行以下操作之一:

  1. 使用桶路径。

我正在考虑对时间戳字段进行最大聚合,为其创建一个bucket_path,并在该bucket_path上运行date_range聚合。这可能是背部疼痛。如果您有问题,请为此创建另一个问题。

  • 将“is_active”字段添加到您的文档中。您可以通过两种方式做到这一点:
  • 2a。每次用户登录时,请在后端代码中添加一个脚本来进行比较。像这样:

    #You get the user_value from your back-end code
    {
        "query":{
            "match": {
                "username": user_value
            }
        },
        "_source": "timestamp" #This will only bring the field timestamp
        "size": 1 #This will only bring back one doc
        "sort":[
            { "timestamp" : {"order" : "desc"}} #This will sort the timestamsps descending
        ]
    }
    

    在后端获取结果。如果您获得的时间戳早于 10 天,请向即将索引的文档添加值 "is_active": 0 #或者您想要的值,例如“no”。在其他情况下 "is_active": 1 #或者您想要的值,例如 'yes'

    2b。在 Logstash 中运行一个脚本来解析信息。这将要求您:

    • 使用 Ruby 脚本
    • 通过后端的套接字发送信息

    希望这对您有帮助! :D

    关于Elasticsearch 日期聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57573293/

    相关文章:

    elasticsearch - Elasticsearch 中的匹配数组

    serialization - 将 Elasticsearch 结果返回为原始JSON

    elasticsearch - 配置Grafana数据源以使用多个ElasticSearch节点

    elasticsearch - ElasticSearch 5.2用空格分隔句子

    maven - 传递依赖 : Using Elasticsearch Rest High Client problem in AEM

    elasticsearch - 如何计算 Elasticsearch 聚合每个步骤的平均天数?

    api - Elasticsearch 查询,用于在文档包含所有特定属性集时显示文档

    elasticsearch - `terms` 聚合的条件

    sql - 为嵌套的 Elasticsearch 结构格式化 Postgres JSON 输出

    java - Elasticsearch 不适用于 Shopizer