【问题标题】:Elasticsearch - Aggregating on multiple fields, filtering on count and ordering on countElasticsearch - 聚合多个字段,按计数过滤并按计数排序
【发布时间】:2019-03-20 05:37:06
【问题描述】:

我对聚合有点陌生,我想创建一个等效于以下 SQL 的语句:

select fullname, natcode, count(1) from table where birthdate = '18-sep-1993' group by fullname, natcode having count(1) > 2 order by count(1) desc

所以,如果我有以下数据:

我需要得到结果为:

如您所见,结果按全名和natcode分组,有count>2并按count排序

我已经设法形成以下查询:

{
  "size": 0,
  "aggs": {
    "profs": {
      "filter": {
        "term": {
          "birthDate": "18-Sep-1993"
        }
      },
      "aggs": {
        "name_count": {
          "terms": {
            "field": "fullName.raw"
          },
          "aggs": {
            "nat_count": {
              "terms": {
                "field": "natCode"
              },
              "aggs": {
                "my_filter": {
                  "bucket_selector": {
                    "buckets_path": {
                      "the_doc_count": "_count"
                    },
                    "script": {
                      "source": "params.the_doc_count>2"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

实现了什么: 它在日期上过滤,在全名(name_count)上创建桶,在 natcode(nat_count)上创建子桶,并在文档计数上过滤 natcode 桶。

这个问题: 我也可以看到空的 name_count 存储桶。我只想要具有所需计数的存储桶。以下是结果示例

"aggregations": {
    "profs": {
      "doc_count": 3754,
      "name_count": {
        "doc_count_error_upper_bound": 4,
        "sum_other_doc_count": 3732,
        "buckets": [
          {
            "key": "JOHN SMITH",
            "doc_count": 3,
            "nat_count": {
              "doc_count_error_upper_bound": 0,
              "sum_other_doc_count": 0,
              "buckets": [
                {
                  "key": "111",
                  "doc_count": 3
                }
              ]
            }
          },
          {
            "key": "MIKE CAIN",
            "doc_count": 3,
            "nat_count": {
              "doc_count_error_upper_bound": 0,
              "sum_other_doc_count": 0,
              "buckets": [
                {
                  "key": "205",
                  "doc_count": 3
                }
              ]
            }
          },
          {
            "key": "JULIA ROBERTS",
            "doc_count": 2,
            "nat_count": {
              "doc_count_error_upper_bound": 0,
              "sum_other_doc_count": 0,
              "buckets": []
            }
          },
          {
            "key": "JAMES STEPHEN COOK",
            "doc_count": 2,
            "nat_count": {
              "doc_count_error_upper_bound": 0,
              "sum_other_doc_count": 0,
              "buckets": []
            }
          }

在结果中,我不想显示最后两个名字(JULIA ROBERTS 和 JAMES STEPHEN COOK)

另外缺少什么: 组的排序在最后。我希望显示计数最多的组(全名、natcode)

进一步要求: 分组需要在另外几个字段上完成,所以它们就像 4 个字段。

如果我可能使用了任何错误的术语,请原谅。希望您了解需要什么帮助。谢谢

【问题讨论】:

    标签: elasticsearch elasticsearch-aggregation


    【解决方案1】:

    以下是您的查询应该是怎样的。

    必填查询(最终答案)

    POST <your_index_name>/_search
    {
      "size": 0,
      "query": {
        "bool": {
          "filter": {
            "term": {
              "birthDate": "18-sep-1993"
            }
          }
        }
      }, 
      "aggs": {
        "groupby_fullname": {
          "terms": {
            "field": "fullName.raw",
            "size": 2000
          },
          "aggs": {
            "natcode_filter": {
              "bucket_selector": {
                "buckets_path": {
                  "hits": "groupby_natcode._bucket_count"
                },
                "script": "params.hits > 0"
              }
            },
            "groupby_natcode": {
              "terms": {
                "field": "natCode",
                "size": 2000,
                "min_doc_count": 2
              }
            }
          }
        }
      }
    }
    

    替代方案:(类似选择 distinct)

    作为最后的手段,我能想出的是根据fullName + "_" + natCode 选择不同的东西。所以基本上你的钥匙的形式是JOHN SMITH_111。这确实为您提供了准确的结果,除了键将采用这种形式。

    POST <your_index_name>/_search
    {  
       "size":0,
       "query":{  
          "bool":{  
             "filter":{  
                "term":{  
                   "birthDate":"18-sep-1993"
                }
             }
          }
       },
       "aggs":{  
          "name_count":{  
             "terms":{  
                "script":{  
                   "inline":"doc['fullName.raw'].value + params.param + doc['natCode'].value",
                   "lang":"painless",
                   "params":{  
                      "param":"_"
                   }
                }
             },
             "aggs":{  
                "my_filter":{  
                   "bucket_selector":{  
                      "buckets_path":{  
                         "doc_count":"_count"
                      },
                      "script":"params.doc_count > 2"
                   }
                }
             }
          }
       }
    }
    

    希望对您有所帮助。

    【讨论】:

    • 您建议的查询没有给我预期的结果。我更新了样本数据和所需结果的更多详细信息。
    • @Maarab 我得到了字段名的情况(输入全名而不是全名Name 错误。请您现在测试查询并告诉我它是否有效。正在运行上面的查询(两者),根据您在问题中提到的数据,给出了您正在寻找的结果。
    • 数据样本中的全名是 db 列名。我运行了查询,但在结果中没有得到任何存储桶(对不起,不知道如何格式化) 结果 1:"aggregations": { "profs": { "doc_count": 53, "name_count": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 42, "buckets": [] } } } 结果 2:"aggregations": { "name_count": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 42, "buckets": [] } }
    • @Maarab 道歉。我错误地使用了 "birthDate": "18-Sep-1933" 而不是 "birthDate": "18-Sep-1993" 我在答案中更正了。请再试一次,同样的查询,让我知道它是否有效。如果还是不行,请分享您的映射详细信息。
    • 是的,我刚刚运行它,它似乎给了我我需要的东西,但我需要进行更多测试才能得出结论。您对过滤器的建议也非常正确。第二个查询是查询的结构,即首先过滤然后应用聚合。将尝试在测试后发布最终更新。
    猜你喜欢
    • 2021-02-06
    • 2021-01-30
    • 2022-01-10
    • 2015-07-12
    • 1970-01-01
    • 2018-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    相关资源
    最近更新 更多