elasticsearch - 具有过滤器匹配的Elasticsearch聚合

标签 elasticsearch elasticsearch-aggregation

我有一个带有嵌套文档集合的文档:

{
  "_source": {
    ...
    "groups": [
      {
        "group_id": 100,
        "parent_group_id": 1,
        "title": "Wheel",
        "parent_group_title": "Parts"
      },
      {
        "group_id": 200,
        "parent_group_id": 2,
        "title": "Seat",
        "parent_group_title": "Parts"
      }
    ]
    ...
  }
}

映射将显示下一个:

{
  ...,

  "groups": {
    "type": "nested",
    "properties": {
      "group_id": {
        "type": "long"
      },
      "title": {
        "type": "text",
        "analyzer": "my_custom_analyzer",
        "term_vector": "with_positions_offsets",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "parent_group_id": {
        "type": "long"
      },
      "parent_group_title": {
        "type": "text",
        "analyzer": "my_custom_analyzer",
        "term_vector": "with_positions_offsets",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  },

  ...
}

我正在尝试做的是下一个聚合:

{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "groups",
            "query": {
              "match": {
                "groups.title": {
                  "query": "whe"
                }
              }
            }
          }
        }
      ]
    }
  },
  "size": 0,
  "aggs": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "nested": {
                "path": "groups",
                "query": {
                  "match": {
                    "groups.title": {
                      "query": "whe"
                    }
                  }
                }
              }
            }
          ]
        }
      },
      "aggs": {
        "groups": {
          "nested": {
            "path": "groups"
          },
          "aggs": {
            "titles": {
              "terms": {
                "field": "groups.title.keyword",
                "size": 5
              },
              "aggs": {
                "parents": {
                  "terms": {
                    "field": "groups.parent_group_title.keyword",
                    "size": 3
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

通过这样的查询,我得到的结果类似于下一个:

  "aggregations" : {
    "filtered" : {
      "doc_count" : ...,
      "groups" : {
        "doc_count" : ...,
        "titles" : {
          "doc_count_error_upper_bound" : ...,
          "sum_other_doc_count" : ...,
          "buckets" : [
            {
              "key" : "Seat",
              "doc_count" : 10,
              "parents" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 10,
                "buckets" : [
                  {
                    "key" : "Parts",
                    "doc_count" : 6
                  },
                  {
                    "key" : "Other",
                    "doc_count" : 4
                  }
                ]
              }
            },
            {
              "key" : "Wheel",
              "doc_count" : 3,
              "parents" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 3,
                "buckets" : [
                  {
                    "key" : "Parts",
                    "doc_count" : 2
                  },
                  {
                    "key" : "Other",
                    "doc_count" : 1
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }

但是我想要的是,只有键Wheel的结果才会出现在结果存储桶中(或与whe搜索字符串匹配的任何其他结果)。

希望这个问题足够清楚。我做错了什么?有什么建议或变化的数据结构或查询吗?

UPD:
添加my_custom_analyzer供引用:
{
  "my_custom_analyzer": {
    "type": "custom",
    "tokenizer": "ngram",
    "filter": [
      "lowercase",
      "asciifolding"
    ],
    "char_filter": [
      "html_strip"
    ],
    "min_gram": 2,
    "max_gram": 15,
    "token_chars": [
      "letter",
      "digit"
    ]
  }
}

最佳答案

您可能要在groups.title组之前进行过滤。这意味着您根本不需要顶级查询,也不需要filtered -level查询。

我没有可用的my_custom_analyzer,因此我使用了基本的匹配项,但您的主旨是:

GET groups/_search
{
  "size": 0,
  "aggs": {
    "groups": {
      "nested": {
        "path": "groups"
      },
      "aggs": {
        "titles": {
          "filter": {
            "match": {
              "groups.title": {
                "query": "wheel"
              }
            }
          },
          "aggs": {
            "group_title_terms": {
              "terms": {
                "field": "groups.title.keyword",
                "size": 5
              },
              "aggs": {
                "parents": {
                  "terms": {
                    "field": "groups.parent_group_title.keyword",
                    "size": 3
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

更新:

分析仪存在问题-让我们使用_analyze来确定whe如何被标记化:
GET groups/_analyze
{
  "text": "whe",
  "analyzer": "my_custom_analyzer"
}

屈服
{
  "tokens" : [
    {
      "token" : "w",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "wh",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "h",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "he",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "e",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 4
    }
  ]
}

我怀疑基于 token eSeats得到匹配。

我的建议是使用edge_ngram代替n_gram,如下所示:
PUT groups
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "tokenizer": "my_tokenizer",
          "filter": [
            "lowercase",
            "asciifolding"
          ],
          "char_filter": [
            "html_strip"
          ]
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "groups": {
        "type": "nested",
        "properties": {
          "group_id": {
            "type": "long"
          },
          "title": {
            "type": "text",
            "analyzer": "my_custom_analyzer",
            "term_vector": "with_positions_offsets",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          },
          "parent_group_id": {
            "type": "long"
          },
          "parent_group_title": {
            "type": "text",
            "analyzer": "my_custom_analyzer",
            "term_vector": "with_positions_offsets",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}

应用映射,重新索引,您就可以开始了!

关于elasticsearch - 具有过滤器匹配的Elasticsearch聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62199911/

相关文章:

string - ElasticSearch数据类型的限制是什么?

java - 如何在elasticsearch中聚合 'non - keyword'字段?

javascript - 尝试在ElasticSearch中进行查询和汇总,但无法正常工作-Elasticsearch.js客户端

elasticsearch - 在es中按嵌套和非嵌套字段分组

ruby-on-rails - 模型类别的Searchkick聚合

elasticsearch - FIWARE Cygnus 下沉到 Elasticsearch/Kibana ?

javascript - 关于 webapp 架构和 ReactJs 的建议

elasticsearch - Elasticsearch 5.6聚合平均而言并非所有存储桶都返回

elasticsearch - Elasticsearch 的最大可滚动时间

elasticsearch - Elasticsearch-如何为双嵌套对象生成构面