使用Bulk API加载Elasticsearch索引失败,Python报406错误求解决
解决Elasticsearch TransportError(406):Content-Type头不支持的问题
这个406错误我之前也碰到过,本质是Elasticsearch版本升级后的强制要求和旧代码的适配问题,具体原因和解决办法如下:
错误原因
- Elasticsearch版本强制要求:从ES 6.0开始,官方明确要求所有写入、修改类的API请求必须携带
Content-Type: application/json请求头,否则就会返回406不支持的错误。你从论坛复制的代码大概率是针对ES 5.x及更早版本编写的,那时候还没有这个强制规则。 - 客户端版本不匹配:如果你的
elasticsearch-py客户端版本和ES服务端版本差距过大,旧版客户端可能不会自动添加这个必要的请求头,导致请求被服务端拒绝。
解决办法
1. 匹配客户端与ES服务端版本
首先确保你安装的elasticsearch-py版本和ES服务端版本对应(比如ES 7.x对应客户端7.x,ES 8.x对应客户端8.x),可以用以下命令安装指定版本:
pip install elasticsearch==7.17.0 # 替换成你的ES服务端实际版本
新版本的客户端会自动处理Content-Type头,不需要手动额外设置。
2. 显式设置请求头(针对旧版客户端)
如果暂时无法升级客户端,可以在创建ES实例或调用API时手动指定请求头:
方法一:创建客户端时全局设置
from elasticsearch import Elasticsearch # 创建客户端时添加默认请求头 es = Elasticsearch( ["http://localhost:9200"], headers={"Content-Type": "application/json"} )
方法二:单个API调用时设置
# 在index、bulk等方法中单独指定headers参数 es.index( index="your_index_name", doc_type="_doc", # ES 7.x及以后版本可以省略该参数 body={"field1": "value1", "field2": "value2"}, headers={"Content-Type": "application/json"} )
3. 确保请求体格式正确
不要直接传递JSON字符串作为body参数,要传递Python字典——客户端会自动将字典序列化为JSON并设置正确的请求头。比如:
❌ 错误写法:
es.index(index="my_index", body='{"field": "value"}')
✅ 正确写法:
es.index(index="my_index", body={"field": "value"})
验证方法
你可以先用curl命令验证ES服务端是否正常响应带正确请求头的请求:
curl -X POST http://localhost:9200/test_index/_doc -H "Content-Type: application/json" -d '{"test": "data"}'
如果这个命令返回成功,说明问题确实出在Python客户端的请求头设置上,按照上面的方法调整即可。
内容的提问来源于stack exchange,提问作者the_data_novice
相关产品推荐
相关产品推荐

