应用聚合后过滤掉弹性搜索中的术语聚合桶

Posted

技术标签:

【中文标题】应用聚合后过滤掉弹性搜索中的术语聚合桶【英文标题】:Filter out terms aggregation buckets in elasticsearch after applying aggregation 【发布时间】:2021-07-03 08:54:23 【问题描述】:

以下是数据集的快照:

recordNo    employeeId      employeeStatus   employeeAddr
1           employeeA       Permanent   
2           employeeA                         ABC
3           employeeB       Contract    
4           employeeB                         CDE

我想获取员工列表以及employeeStatus 和employeeAddr。

所以我在employeeId 上使用术语聚合,然后使用employeeStatus 和employeeAddr 的子聚合来获取这些详细信息。 下面的查询正确返回结果。


    "aggregations": 
        "Employee": 
            "terms": 
                "field": "employeeID"
            
            ,
            "aggregations": 
                "employeeStatus": 
                    "terms": "field": "employeeStatus"
                ,
                "employeeAddr": 
                    "terms": "field": "employeeAddr"
                
            
        
    

        

现在我只想要永久身份的员工。所以我正在应用过滤器聚合。


    "aggregations": 
        "filter_Employee_employeeID": 
            "filter": 
                "bool": 
                    "must": [
                        
                            "match": 
                                "employeeStatus": "query": "Permanent"
                            
                        
                    ]
                
            ,
            "aggregations": 
                "Employee": 
                    "terms": 
                        "field": "employeeID"
                    ,
                    "aggregations": 
                        "employeeStatus": 
                            "terms": "field": "employeeStatus"
                        ,
                        "employeeAddr": 
                            "terms": "field": "employeeAddr"
                        
                    
                
            
        
        


现在的问题是employeeAddr 聚合没有为employeeA 返回任何桶,因为在聚合完成之前记录2 被过滤掉了。

假设我无法修改数据集,我想通过单个弹性查询来达到结果,我该怎么做?

我检查了 Bucket Selector 管道聚合,但它仅适用于指标聚合。 有没有办法在应用聚合后过滤掉术语桶?

【问题讨论】:

您期望的搜索结果是什么? 我需要永久雇员的所有详细信息。因此,例如,预期的输出是应返回employeeA 存储桶,并且在子聚合中,应返回用于employeeStatus 的存储桶“Permanent”和用于employeeAddr 的存储桶“ABC”。目前在结果中,employeeAddr 下没有重新调整“ABC”存储桶,因为过滤器 agg 中的查询删除了数据集的记录 2。 【参考方案1】:

如果我理解正确,即使您使用某种过滤器,您也希望保留聚合。为此,请尝试使用 post_filter 子句。

您可以查看文档here

该子句应用于聚合“外部”。使用您的示例,它应该如下所示:


  "aggregations": 
    "filter_Employee_employeeID": 
      "aggregations": 
        "Employee": 
          "terms": 
            "field": "employeeID"
          ,
          "aggregations": 
            "employeeStatus": 
              "terms": 
                "field": "employeeStatus"
              
            ,
            "employeeAddr": 
              "terms": 
                "field": "employeeAddr"
              
            
          
        
      
    
  ,
  "post_filter": 
    "bool": 
      "must": [
        
          "match": 
            "employeeStatus": 
              "query": "Permanent"
            
          
        
      ]
    
  

【讨论】:

您好,Vitor,感谢您的意见。如果我正确理解了文档,post_filter 将过滤掉响应的“命中”部分中的结果。我需要对聚合结果应用过滤器,因为聚合结果经过处理以显示在客户端。上面我只粘贴了查询的 sn-p,但也有 Employee 下的子实体的子聚合和聚合桶的分页支持,所以我需要层次结构格式的过滤数据。

以上是关于应用聚合后过滤掉弹性搜索中的术语聚合桶的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch 中的术语聚合返回单词而不是完整字段值的存储桶

如何在弹性搜索的过滤器聚合中引用多个嵌套级别?

将聚合限制为弹性搜索中的热门内容

在弹性搜索中不过滤的情况下提升匹配术语查询的结果

Elasticsearch 聚合按每个存储桶的前一个结果进行过滤

使用术语聚合执行搜索时如何返回实际值(不是小写字母)?