在elastic中,我尝试计算字段值的组合。
在SQL中,这将类似于
从tbl GROUP BY a,b中选择a,b,COUNT(a)
(我的数据是Apache logs,我正在计算client_ip+method+response_code的组合)
示例数据
a,b,c,d
a,b,c,d
a,b,c,e
预期输出
a,b,c,d=2
a,b,c,e=1
字段都是文本匹配应该是精确的,而不是模糊的输出需要显示组合和计数我不想在文本字段上启用字段数据,因为我的代码将是开源的,所以我希望对开箱即用的弹性进行最小程度的更改以模拟用户
花了几个小时阅读,我不是更明智的,每个例子都是非常不同的。
感谢任何人的帮助!
我一直在看:
基数,多个基数平均值,组,字段与关键字
发布于 2019-05-20 00:34:08
下面是实现这一目标的三种方法(主要是两种,尽管我已经提到了三种,前两种是相似的):
解决方案1:使用Elasticsearch DSL
我已经提到了示例映射、示例文档、示例聚合查询和响应:
映射:
请注意,我以multi-field格式创建了所有字段。这意味着对于每个类型为text
的字段(例如client_ip
),您都有它的同级字段client_ip.keyword
,它的类型应该是keyword
。它位于聚合查询将起作用的这个字段上。
除非将Text设置为enabled
,否则不能对fielddata
类型运行聚合查询。我不建议这样做,如果你必须这样做,最好使用下面提到的多字段。
PUT myipindex
{
"mappings": {
"mydocs": {
"properties":{
"client_ip": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"method": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"response_code":{
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}
示例文档:
POST myipindex/mydocs/1
{
"client_ip": "10.10.10.10",
"method": "GET",
"response_code": "200"
}
POST myipindex/mydocs/2
{
"client_ip": "10.10.10.10",
"method": "GET",
"response_code": "200"
}
POST myipindex/mydocs/3
{
"client_ip": "10.10.10.11",
"method": "GET",
"response_code": "200"
}
POST myipindex/mydocs/4
{
"client_ip": "10.10.10.11",
"method": "POST",
"response_code": "200"
}
聚合查询:
我简单地在下面的树/子聚合表单中创建了3个Terms Aggregation,以帮助您理解:
Terms Aggregation for client_ip
- Terms Aggregation for method
- Terms Aggregation for response_code
以下是实际的查询:
POST myipindex/_search
{
"size": 0,
"aggs":{
"my_ip":{
"terms": {
"field": "client_ip.keyword",
"size": 10,
"min_doc_count": 1
},
"aggs": {
"my_method": {
"terms": {
"field": "method.keyword",
"size": 10,
"min_doc_count": 1
},
"aggs": {
"my_response_code": {
"terms": {
"field": "response_code.keyword",
"size": 10,
"min_doc_count": 1
}
}
}
}
}
}
}
}
聚合响应:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 4,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"my_ip" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "10.10.10.10",
"doc_count" : 2,
"my_method" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "GET",
"doc_count" : 2,
"my_response_code" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 2
}
]
}
}
]
}
},
{
"key" : "10.10.10.11",
"doc_count" : 2,
"my_method" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "GET",
"doc_count" : 1,
"my_response_code" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 1
}
]
}
},
{
"key" : "POST",
"doc_count" : 1,
"my_response_code" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 1
}
]
}
}
]
}
}
]
}
}
}
解决方案2:将Elasticsearch DSL与无痛脚本结合使用
这个解决方案类似于解决方案1,其中我仍然使用术语聚合,但我已经编写了一个自定义脚本来实现这一点。
考虑到输出格式,我想您可能更喜欢这个而不是解决方案1。
聚合查询:
POST myipindex/_search
{
"size": 0,
"aggs": {
"myagg": {
"terms": {
"script": {
"source": """
return doc['client_ip.keyword'].value + ", " + doc ['method.keyword'].value + ", " + doc['response_code.keyword'].value;
""",
"lang": "painless"
}
}
}
}
}
聚合响应:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 4,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"myagg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "10.10.10.10, GET, 200",
"doc_count" : 2
},
{
"key" : "10.10.10.11, GET, 200",
"doc_count" : 1
},
{
"key" : "10.10.10.11, POST, 200",
"doc_count" : 1
}
]
}
}
}
解决方案3:如果您有Elasticsearch xpack,则使用SQL访问
如果您可以访问xpack的SQL Access特性,那么您可以简单地执行以下查询:
POST /_xpack/sql?format=txt
{
"query": "SELECT client_ip, method, response_code, count(*) FROM myipindex GROUP BY client_ip, method, response_code"
}
响应:
client_ip | method | response_code | COUNT(1)
---------------+---------------+---------------+---------------
10.10.10.10 |GET |200 |2
10.10.10.11 |GET |200 |1
10.10.10.11 |POST |200 |1
如果这有帮助,请告诉我!
https://stackoverflow.com/questions/56209503
复制相似问题