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

i_l*_*ots 37 aggregate faceted-search elasticsearch

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

{
    ...
    meta: {
        ...
        tags: [
            {
                id: 123,
                name: 'Biscuits'
            },
            {
                id: 456,
                name: 'Cakes'
            },
            {
                id: 789,
                name: 'Breads'
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

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

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "item.meta.tags.id": "123"
                    }
                },
                {
                    ...
                }
            ]
        }
    },
    "aggs": {
        "baked_goods": {
            "terms": {
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这很完美,我得到了我想要的结果.但是,我要求标签ID 名称都做有用的事情.我已经探索了如何实现这一点,解决方案似乎是:

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

第一选项和第二选项对我来说是不可用的,所以我一直在使用3,但它没有以预期的方式响应.鉴于以下查询(仍在搜索也标有'Biscuits'的文档):

{
    ...
    "aggs": {
        "baked_goods": {
            "terms": {
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            },
            "aggs": {
                "name": {
                    "terms": {
                        "field": "item.meta.tags.name"
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我会得到这个结果:

{
    ...
    "aggregations": {
        "baked_goods": {
            "buckets": [
                {
                    "key": "456",
                    "doc_count": 11,
                    "name": {
                        "buckets": [
                            {
                                "key": "Biscuits",
                                "doc_count": 11
                            },
                            {
                                "key": "Cakes",
                                "doc_count": 11
                            }
                        ]
                    }
                }
            ]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

嵌套聚合包括搜索项我之后的标记(按字母顺序返回).

我试图通过向exclude嵌套聚合添加一个来缓解这种情况,但这会使查询速度下降得太多(500000个文档大约100次).到目前为止,最快的解决方案是手动重置结果.

在响应中使用标记ID和标记名称聚合标记的最佳方法是什么?

感谢你做到这一点!

And*_*fan 48

从它的外观来看,你tags不是nested.要使此聚合起作用,您需要它nested以便在a 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"
                }
              }
            }
          }
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)

此外,请注意我已添加到此行的映射,这"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"
              }
            }
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

结果是这样的:

   "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
                        }
                     ]
                  }
               },
               .....
Run Code Online (Sandbox Code Playgroud)

  • 最后,是的!我们最终能够花时间创建一个具有正确嵌套字段的新索引,但我担心直到最近才这样做.感谢您抽出时间回答我的问题,我为忽略任何Stack Overflow礼仪而道歉! (2认同)