首页 新闻 会员 周边

ES嵌套字段相关操作

0
悬赏园豆:50 [待解决问题]

大佬们 我遇到一个问题 已知author_info和reference_num是同级的字段 author_info是个聚合字段 想要先对聚合字段author_info.city_chn做term聚合 再对reference_num做sum聚合 请问该怎么写dsl语句

  "aggs": {
    "nested": {
      "nested": {
        "path": "author_info"
      },
      "aggs": {
        "city_chn": {
          "terms": {
            "field": "author_info.city_chn",
            "size": 10
          },
          "aggs": {
            "SUM": {
              "sum": {
                "field": "reference_num"
              }
            }
          }
        }
      }
    }
  }

目前代码如上 明显有问题 结果中sum的值都为0

ES
守矩的主页 守矩 | 初学一级 | 园豆:152
提问于:2024-04-07 15:21
< >
分享
所有回答(1)
0

在Elasticsearch中,要执行这样的聚合操作,你可以使用aggregations对象来定义你的聚合。首先,你需要对author_info.city_chn字段进行terms聚合,然后在该聚合的aggregations中,对reference_num字段进行sum聚合。

以下是一个示例的DSL(Domain Specific Language)语句:

json
{
"size": 0, // 设置为0,因为我们只关心聚合结果,不关心具体的文档
"aggs": {
"cities": {
"terms": {
"field": "author_info.city_chn"
},
"aggs": {
"total_references": {
"sum": {
"field": "reference_num"
}
}
}
}
}
}
在这个查询中:

"size": 0 表示我们不需要返回任何具体的文档,因为我们只对聚合结果感兴趣。
"aggs" 字段定义了我们的聚合。
"cities" 是我们给外层terms聚合定义的名称。
"terms" 是外层聚合的类型,它根据author_info.city_chn字段的值将数据分组。
"field": "author_info.city_chn" 指定了terms聚合使用的字段。
在cities聚合内部,我们又定义了一个名为total_references的聚合,类型为sum。
"sum" 聚合使用reference_num字段来计算每个城市对应的reference_num的总和。
执行这个查询后,你会得到一个响应,其中包含每个城市(author_info.city_chn的值)及其对应的reference_num的总和。每个城市及其总和作为一个条目在aggregations.cities.buckets数组中列出。每个条目将包含城市名称(key字段)和对应的总和(total_references.value字段)。

林熙棠 | 园豆:212 (菜鸟二级) | 2024-04-11 15:54

"field": "author_info.city_chn" 指定了terms聚合使用的字段。->不对的

支持(0) 反对(0) 守矩 | 园豆:152 (初学一级) | 2024-04-11 15:57

嵌套字段不能直接聚合 要先套一层nested
但是套了nested 它就默认在nested中检索 reference_num在外层 所以不会有聚合结果
所以我想知道有无别的办法可以解决这个问题

支持(0) 反对(0) 守矩 | 园豆:152 (初学一级) | 2024-04-11 15:58

@守矩: 我查了一下 看是不是这个意思 :当前的DSL代码中有一个问题:在嵌套聚合内部尝试对外部字段reference_num进行sum聚合是不会成功的,因为reference_num不在嵌套文档的上下文中。在Elasticsearch中,嵌套聚合只能对嵌套字段内的数据进行聚合,而不能直接访问嵌套字段外部的字段。

为了解决这个问题,您需要对每个城市的文档进行迭代,并在应用层面计算这些文档对应的reference_num的总和。这通常意味着您需要对每个城市分别执行查询,并手动汇总结果。

然而,如果您的数据集不大,或者可以接受性能上的损失,您可以考虑使用脚本字段来尝试在查询中计算总和。但请注意,这种方法可能不适合大型数据集,因为它可能会对性能产生负面影响。

以下是一个使用脚本字段的示例,但请慎重考虑是否要在生产环境中使用它:

{
  "size": 0,
  "aggs": {
    "nested_authors": {
      "nested": {
        "path": "author_info"
      },
      "aggs": {
        "cities": {
          "terms": {
            "field": "author_info.city_chn.keyword",
            "size": 10
          },
          "aggs": {
            "total_references": {
              "bucket_script": {
                "buckets_path": {
                  "nested_doc_count": "_count" // 假设你有一个表示嵌套文档数量的聚合
                },
                "script": {
                  "source": "params.nested_doc_count * params._key", // 这里的脚本是示例,实际上不会计算正确的reference_num总和
                  "params": {
                    // 这里应该有一个方法来传递外部文档的reference_num值,但这在Elasticsearch中是不可能的
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

在上面的示例中,我使用了bucket_script聚合,它允许你基于其他聚合的结果来执行脚本计算。然而,这个脚本中的source部分是一个占位符,实际上它不可能直接访问外部字段reference_num的值。

由于您不能直接在一个聚合查询中同时处理嵌套字段和外部字段,您可能需要考虑以下替代方案:

  1. 应用层面处理:首先执行一个聚合查询来获取所有唯一的city_chn值,然后对每个城市执行另一个查询来获取reference_num的总和。在应用层面汇总这些结果。

  2. 预处理数据:在索引文档之前,计算每个城市的reference_num总和,并将这个总和作为一个新的字段添加到文档中。然后您可以直接对这个新字段进行聚合。

  3. 使用父/子关系:如果数据模型允许,您可以将author_inforeference_num设置为父/子关系,然后可以使用父聚合与子聚合来关联这两个字段。但请注意,这种方法通常比嵌套字段更复杂,并可能不适合所有用例。

在大多数情况下,第一种方法(应用层面处理)是最简单和最直接的解决方案,尽管它可能不是性能最优的。

支持(0) 反对(0) 林熙棠 | 园豆:212 (菜鸟二级) | 2024-04-11 16:48
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册