首页 > 解决方案 > 获取 ElasticSearch 中一个字符串字段的平均长度

问题描述

我给出了大量存储在 ES 中的 Json 文件,如下所示:

{
    {
        "_id": "asd123",
        "lang": "en",
        "content": "This is a dog."
    },
    {
        "_id": "asd1",
        "lang": "de",
        "content": "Was ist das?"
    },
    ......
}

每种语言都有多个文档。我想获得汇总统计信息:每种语言的平均内容字符长度,例如:

"en": 26.32
"de": 23.51
...

我应该使用什么 ES 查询?

标签: elasticsearch

解决方案


我尝试使用与您在上面提供的相同字段,基于此我进行了子聚合。使用术语聚合和字符串统计。

链接: https ://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-string-stats-aggregation.html

以下是我在索引中摄取的数据:

“lang”:“en”,“content”:“这是一只狗。”

“lang”:“en”,“content”:“这是一只猫。”

“lang”:“de”,“content”:“是 das 吗?”

“lang”:“en”,“content”:“我叫 John Smith”

lang 和 content 都被映射为文本字段。

使用了以下查询:

"size": 0,
"aggs": {
  "language_split": {
    "terms": {
      "field": "lang.keyword"
    },
    "aggs": {
      "length_of_each_lang": {
        "string_stats": {
          "field": "content.keyword"
        }
      }
    }
  }
}

响应:

"aggregations" : {
  "language_split" : {
    "doc_count_error_upper_bound" : 0,
    "sum_other_doc_count" : 0,
    "buckets" : [
      {
        "key" : "en",
        "doc_count" : 3,
        "length_of_each_lang" : {
          "count" : 3,
          "min_length" : 14,
          "max_length" : 21,
          "avg_length" : 16.333333333333332,
          "entropy" : 3.8118793047756703
        }
      },
      {
        "key" : "de",
        "doc_count" : 1,
        "length_of_each_lang" : {
          "count" : 1,
          "min_length" : 12,
          "max_length" : 12,
          "avg_length" : 12.0,
          "entropy" : 2.8553885422075336
        }
      }
    ]
  }
}

我认为这avg_length是你需要的。

注意:此功能从版本 7.6+ 开始可用:但是,您可能会考虑重新进行映射,因为内容不能被视为“关键字”。

https://www.elastic.co/guide/en/elasticsearch/reference/7.6/search-aggregations-metrics-string-stats-aggregation.html

如果可以这样做,_update_by_query以便您可以向当前映射添加新字段,那么我建议您使用此管道:

PUT _ingest/pipeline/add-length
{
  "processors": [
    {
      "script": {
        "source": """
        ctx.content_length = ctx.content.length();
        """
      }
    }
  ]
}

然后运行以下命令:POST avg-length/_update_by_query?pipeline=add-length

注意:管道将为content_length当前索引添加一个字段名称,相应的值是每个content文档的长度

当管道成功时,以下聚合可能在这种情况下起作用:

GET avg-length/_search
{
  "size": 0,
  "aggs": {
    "isolate_lang": {
      "terms": {
        "field": "lang.keyword"
      },
      "aggs": {
        "average_length_per_lang": {
          "avg": {
            "field": "content_length"
          }
        }
      }
    }
  }
}

响应将是:

"aggregations" : {
  "isolate_lang" : {
    "doc_count_error_upper_bound" : 0,
    "sum_other_doc_count" : 0,
    "buckets" : [
      {
        "key" : "en",
        "doc_count" : 3,
        "average_length_per_lang" : {
          "value" : 16.333333333333332
        }
      },
      {
        "key" : "de",
        "doc_count" : 1,
        "average_length_per_lang" : {
          "value" : 12.0
        }
      }
    ]
  }
}

推荐阅读