Elasticsearch Bulk API批量导入失败及映射配置疑问
你的Elasticsearch批量导入问题排查与解决
咱们来一步步拆解你遇到的问题,先揪出操作里的错误,再搞定映射和批量导入的正确姿势:
一、你操作中的几个关键错误
索引类型不匹配
你创建映射时指定的类型是doc,但批量导入的JSON里写的是_type: "text",ES里的文档类型必须统一。而且从Elasticsearch 7.x版本开始,已经不再推荐自定义类型,默认类型就是_doc,这一步的类型不一致会直接导致解析失败。批量JSON格式不符合要求
Bulk API的核心要求是每行一个JSON对象:第一行是操作指令(比如{"index": ...}),第二行是对应的文档内容,两者必须换行分隔。你提供的示例里两个JSON是连在一起的(}{),没有换行,ES根本没法正确识别文档内容,所以才会报document is empty的错误。映射配置缺失且部分字段类型不合理
- 你没配置文档里存在的
lastversion和samples字段的映射; - 像
description这类可能需要全文搜索的字段,用keyword类型并不合适(keyword只支持精确匹配),换成text类型会更实用; lastversion是日期格式,应该配置成date类型,方便后续按日期范围查询。
- 你没配置文档里存在的
二、正确的映射配置
下面是适配你文档结构的完整映射,包含samples数组的配置(用nested类型,支持对数组内的对象做独立查询,比普通object类型更灵活):
curl -H 'Content-Type: application/json' -XPUT "localhost:9200/stuff" -d' { "mappings": { "properties": { # ES 7+ 无需指定_type,默认使用_doc "lastversion": {"type": "date"}, "attribution": {"type": "keyword"}, "description": { "type": "text", "fields": {"keyword": {"type": "keyword", "ignore_above": 256}} # 同时支持全文搜索和精确匹配 }, "notes": {"type": "keyword"}, "alt_names": {"type": "keyword"}, "sources": {"type": "keyword"}, "urls": {"type": "keyword"}, "common_name": {"type": "keyword"}, "samples": { "type": "nested", "properties": { "status": {"type": "keyword"}, "sha256": {"type": "keyword"}, "version": {"type": "keyword"} } } } } }'
三、批量导入的正确操作
1. 修正单个JSON文件的格式
每个JSON文件必须改成换行分隔的结构,比如:
{"index": {"_index": "stuff", "_id": "1"}} {"lastversion":"2018-01-19","attribution":[],"description":"","notes":[],"alt_names":[],"sources":[],"urls":["https://www.fireeye.com/blog/threat-research/2018/01/microsoft-office-vulnerabilities-used-to-distribute-zyklon-malware.html"],"common_name":"anonym","samples":[{"status":"dumped","sha256":"8d0be4dd8b0ca7608bf3a02a2d212ce845ac733d150b4428376a5a939f1679ec","version":""}]}
注意:文件最后也要留一个换行,避免ES解析最后一行时出错。
2. 批量处理1000个JSON文件
如果你的1000个文件都是连在一起的JSON格式,可以用shell命令批量拆分并合并成一个大的批量导入文件:
# 遍历所有json文件,拆分合并成bulk_all.ndjson for file in *.json; do # 把连在一起的}{替换成}\n{,实现换行拆分 sed 's/}{/}\n{/' "$file" >> bulk_all.ndjson done # 执行批量导入 curl -H 'Content-Type: application/x-ndjson' -XPOST "localhost:9200/_bulk" --data-binary @bulk_all.ndjson
3. 简化导入命令(可选)
如果所有文档都导入到stuff索引,操作指令里可以省略_index,进一步简化JSON内容:
{"index": {"_id": "1"}} # 后面跟文档内容...
对应的导入命令可以写成:
curl -H 'Content-Type: application/x-ndjson' -XPOST "localhost:9200/stuff/_bulk" --data-binary @bulk_all.ndjson
内容的提问来源于stack exchange,提问作者creed
相关产品推荐
相关产品推荐

