首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多列基数/分组?

多列基数/分组?
EN

Stack Overflow用户
提问于 2019-05-19 23:54:28
回答 1查看 72关注 0票数 0

在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

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

花了几个小时阅读,我不是更明智的,每个例子都是非常不同的。

感谢任何人的帮助!

我一直在看:

基数,多个基数平均值,组,字段与关键字

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-20 00:34:08

下面是实现这一目标的三种方法(主要是两种,尽管我已经提到了三种,前两种是相似的):

解决方案1:使用Elasticsearch DSL

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

映射:

请注意,我以multi-field格式创建了所有字段。这意味着对于每个类型为text的字段(例如client_ip ),您都有它的同级字段client_ip.keyword,它的类型应该是keyword。它位于聚合查询将起作用的这个字段上。

除非将Text设置为enabled,否则不能对fielddata类型运行聚合查询。我不建议这样做,如果你必须这样做,最好使用下面提到的多字段。

代码语言:javascript
复制
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"
            }
          }
        }
      }
    }
  }
}

示例文档:

代码语言:javascript
复制
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,以帮助您理解:

代码语言:javascript
复制
Terms Aggregation for client_ip
- Terms Aggregation for method
 - Terms Aggregation for response_code

以下是实际的查询:

代码语言:javascript
复制
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
              }
            }
          }
        }
      }
    }
  }
}

聚合响应:

代码语言:javascript
复制
{
  "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。

聚合查询:

代码语言:javascript
复制
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"
        }
      }
    }
  }
}

聚合响应:

代码语言:javascript
复制
{
  "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特性,那么您可以简单地执行以下查询:

代码语言:javascript
复制
POST /_xpack/sql?format=txt
{
  "query": "SELECT client_ip, method, response_code, count(*) FROM myipindex GROUP BY client_ip, method, response_code"

}

响应:

代码语言:javascript
复制
   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              

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56209503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档