当前位置: 首页 > 知识库问答 >
问题:

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

司徒俊雄
2023-03-14
{
    ...
    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. 嵌套聚合

选项一和选项二对我来说是不可用的,所以我一直在用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和标记名称的标记聚合的最佳方法是什么?

谢谢你走了这么远!

共有1个答案

姬捷
2023-03-14

从外观上看,您的标记不是嵌套的。要使该聚合发挥作用,需要将其嵌套在,以便在IDname之间有关联。如果没有嵌套IDs的列表只是一个数组,而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,这意味着嵌套的标记的行为也类似于“平面”数组结构。

因此,到目前为止,您在查询中所做的一切都将继续工作,而不对查询进行任何更改。

但是,对于您的这个特定查询,聚合需要更改为如下所示:

{
  "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
                        }
                     ]
                  }
               },
               .....
 类似资料:
  • 问题内容: 我试图找到与当前正在查看的标签相关的标签。我们索引中的每个文档都被标记。每个标签由两部分组成-ID和文本名称: 要获取相关标签,我只是查询文档并获取其标签的集合: 这非常有效,我得到了想要的结果。但是,我需要标签ID 和 名称才能执行任何有用的操作。我已经探索了如何做到这一点,解决方案似乎是: 索引时合并字段 将字段拼凑在一起的脚本 嵌套聚合 选项1和2对我不可用,因此我一直在使用3,

  • 这个问题不是如何通过多个字段进行聚合,我们可以使用子聚合。 如果你知道SQL,我可以给你一个完美的解释: 我们能在Elasticsearch中实现这一点吗? 谢谢。

  • 我在elasticsearch中有一个文档索引,每个文档有480个字段。我试图做的是搜索一个词(例如“Apple”),并获得所有其值与搜索词匹配的唯一字段名。所以如果我的文档是: 作为查询的结果,我希望得到如下所示的聚合: 由于每个文档都有480个字段,所以我更喜欢执行multi_match查询,而不是使用包含所有字段的筛选器: 这个查询在ElasticSearch中可能吗?

  • 我需要按9个文件分组,并在ElasticSearch中获得每个组的计数,原始代码使用“脚本”,性能很差,所以我需要优化它。我设法创建了一个新的字段并使用“copy_to”,但是当我与新的字段聚合时,我发现了一些问题。 我使用“src ip”和“dst ip”字段作为测试,copy_to字段是“agg condition”。下面是映射: 然后我给它添加一些数据 然后我看到kibana中的映射,它看起

  • 我是Elasticsearch的新手,我的程序有问题。 为了将结果分组,如SQL中的“group by”语句。我使用了聚合。 但我意识到这里有一个问题需要解决。我使用以下语句对我的结果进行分组: 我的问题是:字段2和字段3的值取决于字段1的值,所以如果你可以得到字段1的值,你也可以得到字段2和字段3的值。因此,像上面这样进行聚合会花费很多时间来完成我的程序(我已经测试过它,并意识到它比只对字段1进

  • 如何在多个字段上执行聚合?也就是说,我想列出“field1”和“field2”的术语聚合结果,不是单独列出,而是在同一个桶中列出。在elasticsearch中可能吗?