多列 Cardinal/ Groupby?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (20)

在弹性我试图计算字段值的组合。

在SQL中,这就像

SELECT a,b,COUNT(a)FROM tbl GROUP BY a,b

(我的数据是Apache日志,我正在计算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

字段都是文本匹配应该是精确的,而不是模糊输出需要显示组合和计数我不想在文本字段上启用fielddata,因为我的代码将是开源所以我想要对开箱即用的弹性进行微小的更改模仿用户

花了几个小时阅读并且不是明智的,每个例​​子都与此截然不同。

任何帮助赞赏!

提问于
用户回答回答于

下面是三种方式(主要是两种,虽然我已经提到过三种,前两种相似)来实现这个目的:

解决方案1:使用Elasticsearch DSL

我已经提到过示例映射,示例文档,示例聚合查询和响应:

制图:

请注意,我已经以多字段格式创建了所有字段。这意味着对于每个类型的字段,text例如client_ip,你有它的兄弟字段client_ip.keyword类型keyword。它在这个字段下面聚合查询会起作用。

除非已设置为,否则无法对文本类型运行聚合查询。我不建议这样做,如果你必须这样做,最好使用如下所述的多字段。fielddataenabled

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 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,我仍在使用Term Aggregation,但我已经编写了一个自定义脚本来执行此操作。

由于输出格式,您可能希望在解决方案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 Access

如果您可以访问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              

如果这有帮助,请告诉我!

扫码关注云+社区

领取腾讯云代金券