📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 6.8-8.9

1. 错误说明 #

analysis failed 表示 Elasticsearch 在文本分析(analysis)阶段发生了异常。文本分析是 Elasticsearch 处理文本字段的核心环节,发生在:

  • 索引时:对 text 类型字段进行分词、归一化,生成倒排索引
  • 查询时:对 matchmatch_phrase 等全文查询中的查询字符串进行分词

当分析器配置错误、分词器不可用、或输入数据与分析器不兼容时,就会触发此异常。

常见现象 #

  • 写入文档时返回 400 Bad Request,错误信息包含 analysis failed
  • 执行全文搜索时返回 search_phase_execution_exception,根因为分析失败
  • 索引状态变为 redyellow,因为新索引创建后映射(mapping)无法正常初始化
  • Kibana 或应用程序在查询时报错,提示无法对指定字段执行分析

典型报错与异常栈 #

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "analysis failed on [content]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "analysis failed on [content]",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Unknown analyzer [my_custom_analyzer]"
    }
  },
  "status": 400
}

更复杂的异常栈可能如下:

ElasticsearchException: analysis failed
Caused by: IllegalArgumentException: Unknown analyzer [pinyin_analyzer]
    at org.elasticsearch.index.analysis.AnalysisRegistry.getAnalyzer(AnalysisRegistry.java:271)
    at org.elasticsearch.index.analysis.AnalysisRegistry.buildMappingAnalyzer(AnalysisRegistry.java:331)
    ...
Caused by: MapperParsingException: analyzer [pinyin_analyzer] not found for field [title]

2. 原因分析 #

analysis failed 的根本原因在于 Elasticsearch 无法按预期完成文本分析流程。常见原因包括:

2.1 分析器不存在或配置错误 #

索引中引用了未定义的分析器。例如,在 mapping 中指定了自定义分析器,但未在索引的 settings.analysis 中定义它:

PUT /my_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_custom_analyzer"
      }
    }
  }
}

上述请求会报错,因为 my_custom_analyzer 未在 settings.analysis 中定义。

2.2 插件未安装 #

某些分析器依赖插件(如 ikpinyinsmartcnicu 等),如果索引引用了这些分析器但对应插件未安装,就会报错:

{
  "error": {
    "reason": "analyzer [ik_max_word] not found"
  }
}

2.3 分析器配置参数错误 #

自定义分析器的 tokenizerfilterchar_filter 配置有误,例如引用了不存在的过滤器:

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "nonexistent_filter"]
        }
      }
    }
  }
}

2.4 索引模板与索引设置不一致 #

索引模板中定义了分析器,但实际创建索引时模板未生效,或者索引是从旧集群恢复的,分析器定义丢失。

2.5 嵌套或动态映射触发分析失败 #

当动态映射尝试为某个字段推断类型并使用默认分析器,但该字段的内容触发了分析器异常。

2.6 集群滚动升级或节点重启后分析器不可用 #

升级后某些自定义插件分析器在新版本中不再兼容,或者节点重启后插件未正确加载,导致已有索引的分析器不可用。

3. 解决方案 #

3.1 确认报错的具体分析器和字段 #

首先通过错误响应或日志确认是哪个分析器、哪个字段出了问题:

# 查看报错索引的 mapping
GET /my_index/_mapping

# 查看索引的 analysis 配置
GET /my_index/_settings

3.2 检查分析器是否已定义 #

针对报错的分析器名称,检查索引的 settings.analysis 中是否有对应定义:

GET /my_index/_settings

如果返回结果中没有对应的分析器定义,说明分析器未正确配置,需要补充定义或切换到已存在的分析器。

3.3 补充缺失的分析器定义(新建索引场景) #

如果是新建索引时报错,需要在创建索引时正确配置分析器:

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "stop"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_custom_analyzer"
      }
    }
  }
}

3.4 修改已有索引的映射(Reindex 方案) #

已有索引无法直接修改 mapping 中的 analyzer,需要通过 Reindex 解决:

# 1. 创建新索引,正确配置分析器
PUT /my_index_new
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_custom_analyzer"
      }
    }
  }
}

# 2. 重建索引
POST /_reindex
{
  "source": { "index": "my_index" },
  "dest": { "index": "my_index_new" }
}

# 3. 创建别名切换
POST /_aliases
{
  "actions": [
    { "remove": { "index": "my_index", "alias": "my_index_alias" } },
    { "add":    { "index": "my_index_new", "alias": "my_index_alias" } }
  ]
}

3.5 检查并安装缺失的插件 #

如果报错分析器来自插件(如 ikpinyin 等),需要在所有节点安装对应插件并重启:

# 查看已安装插件
GET /_cat/plugins?v

# 在每台节点上安装 IK 分词插件(示例)
# bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/8.9.0

# 安装后重启节点

3.6 使用 _analyze API 调试分析器 #

使用 _analyze API 可以直接测试分析器是否正常工作:

POST /my_index/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "测试文本分析是否正常工作"
}

如果分析器配置有问题,该 API 会直接返回错误,便于快速定位。

3.7 临时规避方案:修改字段分析器 #

如果短期内无法修复分析器配置,可以临时将字段改为使用内置分析器(如 standardkeyword):

PUT /my_index/_mapping
{
  "properties": {
    "title": {
      "type": "text",
      "analyzer": "standard"
    }
  }
}

注意:已有字段的 analyzer 无法直接修改,此操作只对新写入的字段生效,已有数据需要 Reindex。

4. 预防措施 #

4.1 在索引模板中统一定义分析器 #

使用索引模板(Index Template)确保所有新索引都包含正确的分析器配置:

PUT /_index_template/my_template
{
  "index_patterns": ["my_logs_*"],
  "template": {
    "settings": {
      "analysis": {
        "analyzer": {
          "default": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": ["lowercase", "stop"]
          }
        }
      }
    },
    "mappings": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "default"
        }
      }
    }
  }
}

4.2 在变更前使用 _analyze 验证分析器 #

在修改分析器配置或上线新索引前,先用 _analyze API 验证配置是否正确:

POST /_analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase", "stop"],
  "text": "The quick brown fox jumps over the lazy dog"
}

4.3 确保所有节点插件版本一致 #

如果使用自定义分析器插件,确保:

  • 所有节点都安装了相同版本的插件
  • 升级集群前,先确认插件兼容目标版本
  • 使用配置管理工具统一部署插件

4.4 监控索引创建事件 #

通过监控索引创建事件,及时发现分析器配置错误:

GET /_cat/indices?v&h=index,status,creation.date.string

4.5 在应用程序中做好异常处理 #

在应用层捕获 analysis failed 异常,给出明确的错误提示:

try {
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
    if (e.getMessage().contains("analysis failed")) {
        log.error("分析器配置错误,请检查索引 mapping 和分析器定义", e);
    }
}

5. 小结 #

analysis failed 是 Elasticsearch 文本分析阶段的典型异常,核心原因是分析器不可用或配置错误。排查时应优先确认:

  1. 报错的分析器名称是什么
  2. 该分析器是否在索引 settings.analysis 中正确定义
  3. 如果依赖插件,插件是否已安装且版本兼容

修复方案通常是补充分析器定义后 Reindex,或通过索引模板确保新索引的配置正确性。借助 INFINI Console 可以方便地查看索引 mapping、分析器配置和集群插件状态,快速定位分析失败的根因; INFINI Gateway 则可以在请求层面拦截异常分析请求,保护后端集群稳定性。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

analysis failed
Caused by: ElasticsearchException
Caused by: IllegalArgumentException: Unknown analyzer [analyzer_name]
    at org.elasticsearch.index.analysis.AnalysisRegistry.getAnalyzer(AnalysisRegistry.java:271)