You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计ElasticSearch索引文档指定字段中特定词的出现次数

Runtime字段+Painless完整可运行方案

这个方案无需修改现有索引,查询时动态计算计数,适合临时统计场景,返回结果会同时携带原始_source和两个新增的计数字段。
注意:以下脚本默认统计分词后精确匹配"US"词元的出现次数,和ES普通搜索的匹配逻辑完全一致,直接复用倒排索引统计数据,性能远高于字符串遍历。

GET profile_similarity/_search
{
  "runtime_mappings": {
    "country_count_US": {
      "type": "long",
      "script": {
        "source": """
          String target = "US";
          if (doc['country'].isEmpty()) {
            emit(0L);
            return;
          }
          emit(doc['country'].termFreq(target));
        """
      }
    },
    "headline_count_US": {
      "type": "long",
      "script": {
        "source": """
          String target = "US";
          if (doc['headline'].isEmpty()) {
            emit(0L);
            return;
          }
          emit(doc['headline'].termFreq(target));
        """
      }
    }
  },
  "query": {
    "match_all": {} // 这里可以替换成你需要的任意查询条件
  },
  "_source": true, // 返回原始文档内容
  "fields": ["country_count_US", "headline_count_US"] // 返回计算得到的计数字段
}

如果你的需求是不考虑分词逻辑,直接统计原始字符串中"US"子串的出现次数(比如需要匹配"USA"、"US123"这类包含US子串的内容),把runtime字段里的脚本替换为以下版本即可,这个版本直接读取原始_source内容做字符串匹配:

// 统计country字段时用这段,统计headline字段把params._source.country改成params._source.headline即可
String target = "US";
String content = params._source.country;
if (content == null || content.length() < target.length()) {
  emit(0L);
  return;
}
int count = 0;
int idx = 0;
while ((idx = content.indexOf(target, idx)) != -1) {
  count++;
  idx += target.length();
}
emit((long)count);

其他ES原生实现方案

以下方案适合生产环境长期使用,查询性能比查询时动态脚本计算高很多:

  • Ingest Pipeline预处理(最推荐生产用)
    文档写入索引前,通过ES原生的Ingest节点配置脚本处理器,提前计算好指定关键词的出现次数,作为独立的long类型字段存入文档。查询时直接读取预计算的数值字段,完全没有运行时计算开销,性能最高,适合关键词固定、查询频率高的场景。
  • Term Vectors API
    如果只是偶尔查询单条或少量文档的关键词出现次数,可以直接调用ES原生的_termvectors接口,指定文档ID、字段名和目标term,接口会直接返回该term在对应字段的出现频次、位置、偏移量等信息,完全不需要自己编写脚本。
  • 预存储Term Vector
    给对应text字段在mapping中配置"term_vector": "with_positions_offsets",写入文档时ES会提前存储所有词元的统计信息,查询时不需要加载fielddata,也不需要遍历字符串,做term统计的性能远高于fielddata方案,同时不会占用堆内存导致GC问题,适合需要频繁做词元统计的业务场景。

生产环境注意:你当前给text字段开启了fielddata,fielddata是堆内存常驻结构,索引数据量较大时很容易触发长时间GC甚至内存溢出,如果不是临时查询使用,不建议长期依赖fielddata做运行时计算。

内容的提问来源于stack exchange,提问作者ivan100096

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:09:59