一尘不染

如何获得具有多个字段的Elasticsearch聚合

elasticsearch

我试图找到与当前正在查看的标签相关的标签。我们索引中的每个文档都被标记。每个标签由两部分组成-ID和文本名称:

{
    ...
    meta: {
        ...
        tags: [
            {
                id: 123,
                name: 'Biscuits'
            },
            {
                id: 456,
                name: 'Cakes'
            },
            {
                id: 789,
                name: 'Breads'
            }
        ]
    }
}

要获取相关标签,我只是查询文档并获取其标签的集合:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "item.meta.tags.id": "123"
                    }
                },
                {
                    ...
                }
            ]
        }
    },
    "aggs": {
        "baked_goods": {
            "terms": {
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            }
        }
    }
}

这非常有效,我得到了想要的结果。但是,我需要标签ID 名称才能执行任何有用的操作。我已经探索了如何做到这一点,解决方案似乎是:

  1. 索引时合并字段
  2. 将字段拼凑在一起的脚本
  3. 嵌套聚合

选项1和2对我不可用,因此我一直在使用3,但是它没有以预期的方式响应。给定以下查询(仍在搜索还标有“饼干”的文档):

{
    ...
    "aggs": {
        "baked_goods": {
            "terms": {
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            },
            "aggs": {
                "name": {
                    "terms": {
                        "field": "item.meta.tags.name"
                    }
                }
            }
        }
    }
}

我会得到以下结果:

{
    ...
    "aggregations": {
        "baked_goods": {
            "buckets": [
                {
                    "key": "456",
                    "doc_count": 11,
                    "name": {
                        "buckets": [
                            {
                                "key": "Biscuits",
                                "doc_count": 11
                            },
                            {
                                "key": "Cakes",
                                "doc_count": 11
                            }
                        ]
                    }
                }
            ]
        }
    }
}

嵌套聚合包括搜索字词 我后面的标签(按字母顺序返回)。

我试图通过向exclude嵌套聚合中添加来缓解这种情况,但这使查询的速度降低了太多(对于500000个文档而言,约为100倍)。到目前为止,最快的解决方案是手动对结果进行重复数据删除。

在响应中同时包含标签ID和标签名称的标签聚合的最佳方法是什么?

感谢您到目前为止!


阅读 1054

收藏
2020-06-22

共1个答案

一尘不染

从外观上看,您tags不是nested。为了使此聚合起作用,您需要它,nested以便an id和a 之间存在关联name。没有s nested的列表id只是一个数组,而names
的列表是另一个数组:

    "item": {
      "properties": {
        "meta": {
          "properties": {
            "tags": {
              "type": "nested",           <-- nested field
              "include_in_parent": true,  <-- to, also, keep the flat array-like structure
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }

另外,请注意,我已经在映射中添加了这一行"include_in_parent": true,这意味着您的nested标签也将像“平面”数组状结构一样工作。

因此,到目前为止,您在查询中拥有的所有内容仍然可以正常使用,而无需对查询进行任何更改。

但是,对于您的这个特定查询,聚合需要更改为以下内容:

{
  "aggs": {
    "baked_goods": {
      "nested": {
        "path": "item.meta.tags"
      },
      "aggs": {
        "name": {
          "terms": {
            "field": "item.meta.tags.id"
          },
          "aggs": {
            "name": {
              "terms": {
                "field": "item.meta.tags.name"
              }
            }
          }
        }
      }
    }
  }
}

结果是这样的:

   "aggregations": {
      "baked_goods": {
         "doc_count": 9,
         "name": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
               {
                  "key": 123,
                  "doc_count": 3,
                  "name": {
                     "doc_count_error_upper_bound": 0,
                     "sum_other_doc_count": 0,
                     "buckets": [
                        {
                           "key": "biscuits",
                           "doc_count": 3
                        }
                     ]
                  }
               },
               {
                  "key": 456,
                  "doc_count": 2,
                  "name": {
                     "doc_count_error_upper_bound": 0,
                     "sum_other_doc_count": 0,
                     "buckets": [
                        {
                           "key": "cakes",
                           "doc_count": 2
                        }
                     ]
                  }
               },
               .....
2020-06-22