代码之家  ›  专栏  ›  技术社区  ›  Mainuddin

具有分层类别、子类别的ElasticSearch聚合;限制级别

  •  1
  • Mainuddin  · 技术社区  · 6 年前

    我有类别字段的产品。使用聚合,我可以得到所有子类别的完整类别。我想限制侧面的水平。

    例如,我有如下方面:

    auto, tools & travel    (115)
    auto, tools & travel > luggage tags (90)
    auto, tools & travel > luggage tags > luggage spotters  (40)
    auto, tools & travel > luggage tags > something else    (50)
    auto, tools & travel > car organizers   (25)
    

    使用聚合方式

    "aggs": {
        "cat_groups": {
          "terms": {
            "field": "categories.keyword",
            "size": 10,
           "include": "auto, tools & travel > .*"
          }
        }
    }
    

    我得到的水桶就像

    "buckets": [
            {
              "auto, tools & travel > luggage tags",
              "doc_count": 90
            },
            {
              "key": "auto, tools & travel > luggage tags > luggage spotters",
              "doc_count": 40
            },
            {
              "key": "auto, tools & travel > luggage tags > something else",
              "doc_count": 50
            },
            {
              "key": "auto, tools & travel > car organizers",
              "doc_count": 25
            }
    ]
    

    但我想限制这个水平。我只想得到 auto, tools & travel > luggage tags . 如何限制级别? 顺便说一句, "exclude": ".* > .* > .*" 对我不起作用。

    我需要根据搜索得到不同级别的桶。有时是第一级,有时是第二级或第三级。当我想要第一个级别时,我不希望第二个级别出现在bucket上;对于其他级别,以此类推。

    ElasticSearch版本6.4

    2 回复  |  直到 6 年前
        1
  •  1
  •   Kamal Kunjapur    6 年前

    我终于想出了下面的技巧。

    我已经实施了 custom analyzer 使用 Path Hierarchy Tokenizer 我已经创建了多个字段 categories 所以你可以用 categories.facets 对于聚合/方面,使用 类别

    自定义分析器将只应用于 类别.面

    注意这个属性 "fielddata": "true" 为我的领域 categories.facet

    映射

    PUT myindex
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "my_tokenizer"
            }
          },
          "tokenizer": {
            "my_tokenizer": {
              "type": "path_hierarchy",
              "delimiter": ">"
            }
          }
        }
      },
      "mappings": {
        "mydocs": {
          "properties": {
            "categories": {
              "type": "text",
              "fields": {
                "facet": { 
                  "type":  "text",
                  "analyzer": "my_analyzer",
                  "fielddata": "true"
                }
              }
            }
          }
        }
      }
    }
    

    示例文档

    POST myindex/mydocs/1
    {
        "categories" : "auto, tools & travel > luggage tags > luggage spotters"
    }
    
    POST myindex/mydocs/2
    {
        "categories" : "auto, tools & travel > luggage tags > luggage spotters"
    }
    
    POST myindex/mydocs/3
    {
        "categories" : "auto, tools & travel > luggage tags > luggage spotters"
    }
    
    POST myindex/mydocs/4
    {
        "categories" : "auto, tools & travel > luggage tags > something else"
    }
    

    查询

    您可以尝试下面的查询。我又一次实现了 Filter Aggregation 因为你只需要特定的词语 Terms Aggregation .

    {
      "size": 0,
      "aggs":{
        "facets": {
          "filter": { 
              "bool": {
                "must": [
                  { "match": { "categories": "luggage"} }
                ]
             }
          },
          "aggs": {
            "categories": {
              "terms": {
                "field": "categories.facet"
              }
            }
          }
        }
      }
    }
    

    回应

    {
        "took": 43,
        "timed_out": false,
        "_shards": {
            "total": 1,
            "successful": 1,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 11,
            "max_score": 0,
            "hits": []
        },
        "aggregations": {
            "facets": {
                "doc_count": 4,
                "categories": {
                    "doc_count_error_upper_bound": 0,
                    "sum_other_doc_count": 0,
                    "buckets": [
                        {
                            "key": "auto, tools & travel ",
                            "doc_count": 4
                        },
                        {
                            "key": "auto, tools & travel > luggage tags ",
                            "doc_count": 4
                        },
                        {
                            "key": "auto, tools & travel > luggage tags > luggage spotters",
                            "doc_count": 3
                        },
                        {
                            "key": "auto, tools & travel > luggage tags > something else",
                            "doc_count": 1
                        }
                    ]
                }
            }
        }
    }
    

    最后回答后讨论聊天

    POST myindex/_search
    {
      "size": 0,
      "aggs":{
        "facets": {
          "filter": { 
              "bool": {
                "must": [
                  { "match": { "categories": "luggage"} }
              ]
            }
          },
          "aggs": {
            "categories": {
              "terms": {
                "field": "categories.facet",
                "exclude": ".*>{1}.*>{1}.*"
              }
            }
          }
        }
      }
    }
    

    注意,我添加了 exclude 用一个 regular expression 以这样的方式,它将不考虑任何方面是有一个以上的事件 >

    如果有帮助的话告诉我。

        2
  •  0
  •   Maica    6 年前

    只需添加一个名为level的整数字段,表示类别在层次结构中的级别。只需计算分隔符“>”的出现次数并将其保存为值。然后将rangequery添加到boolquery。