我正在努力整理一个查询,可能需要一些帮助。这些文件非常简单,仅记录用户的登录时间
{
"timestamp":"2019-01-01 13:14:15",
"username":"theuser"
}
我希望使用以下规则基于今天(例如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"}
谢谢。
答案 0 :(得分:2)
首先,对不起。这将是一个很长的答案。
您可以将“ 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”(空值,可以称为'-infinite')<=时间戳<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
这是因为所有时间戳都存储在一个索引中,并且可以在所有文档上运行。我假设您只想播放最后一个时间戳。您可以执行以下操作之一:
我正在考虑在时间戳字段上进行最大聚合,为它创建一个bucket_path,并在该bucket_path上运行date_range聚合。这可能是背部疼痛。如果您有问题,请为此提出另一个问题。
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 #Or a value you want like 'no'
。在其他情况下,"is_active": 1 #Or a value you want like 'yes'
2b。在logstash中运行脚本以解析信息。这将要求您:
希望这会有所帮助! :D
答案 1 :(得分:1)
感谢凯文,我想我有一个可行的解决方案。无需使用最大日期和最小日期,只需获取登录计数并使用基数汇总即可获得用户数量。我想要的最终数字只是查询返回的三个值的差异。
GET mytest/_search?filter_path=aggregations.username_groups.buckets.key,aggregations.username_groups.buckets.username_counts.value,aggregations.active_and_inactive_and_new.value
{
"size": 0,
"aggs": {
"active_and_inactive_and_new": {
"cardinality": {
"field": "username"
}
},
"username_groups": {
"range": {
"field": "timestamp",
"ranges": [
{
"to": "now-10d/d",
"key": "active_and_inactive"
},
{
"from": "now-10d/d",
"key": "active_and_new"
}
]
},
"aggs": {
"username_counts": {
"cardinality": {
"field": "username"
}
}
}
}
}
}