使用Elasticsearch-Py Bulk Helper向数据流批量索引文档报错求助
使用Elasticsearch Bulk Helper批量索引文档报错的解决方法
问题背景
使用Python Elasticsearch客户端的Bulk Helper向8.5.3版本的ES数据流批量索引文档时,遇到两类报错:
- 初始代码用
_op_type指定操作类型时,报错元数据格式错误 - 改用
create作为操作键后,又出现未知参数报错
初始代码及报错
代码:
for event in raw: tmp = { "@timestamp": event['timestamp'], "event" : {"kwh": event['kwh']}, "location": f"{self.args.location}", "sourcetype": "meterdata", "host.name": f"{self.args.name}" } payload={ "_op_type": "create", "_index": "energiemonitoring", "_source": tmp } payloadlist.append(payload.copy()) payload=json.loads(json.dumps(payloadlist,default=self.make_json_serial)) r = helpers.bulk( self.es_client, payload, raise_on_error=False )
报错:
elasticsearch.BadRequestError: BadRequestError(400, 'illegal_argument_exception', 'Malformed action/metadata line [1], expected field [create], [delete], [index] or [update] but found [_op_type]'
修改后的代码及报错
代码:
payload={ "create": tmp, "_index": "energiemonitoring", }
报错:
elasticsearch.BadRequestError: BadRequestError(400, 'illegal_argument_exception', 'Action/metadata line [1] contains an unknown parameter [@timestamp]'
问题原因
- 冗余的JSON序列化:手动将Python字典列表转为JSON对象后传入Bulk Helper,破坏了客户端对操作元数据的识别逻辑,导致
_op_type被当成普通字段处理 - 操作格式错误:用
create作为操作键时,错误地将文档内容直接赋值给create,而非将元数据放在create中,文档内容单独放在_source
正确写法
写法一:使用_op_type指定操作类型
保留原生Python字典,不做额外序列化:
payloadlist = [] for event in raw: tmp = { "@timestamp": event['timestamp'], "event" : {"kwh": event['kwh']}, "location": f"{self.args.location}", "sourcetype": "meterdata", "host.name": f"{self.args.name}" } payload = { "_op_type": "create", "_index": "energiemonitoring", "_source": tmp } payloadlist.append(payload) # 直接传入原生列表,无需JSON序列化 r = helpers.bulk( self.es_client, payloadlist, raise_on_error=False )
写法二:使用create作为操作键
将元数据放在create键的对应值中,文档内容单独放在_source:
payloadlist = [] for event in raw: tmp = { "@timestamp": event['timestamp'], "event" : {"kwh": event['kwh']}, "location": f"{self.args.location}", "sourcetype": "meterdata", "host.name": f"{self.args.name}" } payload = { "create": {"_index": "energiemonitoring"}, "_source": tmp } payloadlist.append(payload) r = helpers.bulk( self.es_client, payloadlist, raise_on_error=False )
关键提示
- Bulk Helper会自动处理Python字典到ES批量请求格式的转换,禁止手动做JSON序列化,否则会导致元数据解析失败
- 两种操作格式二选一即可,确保操作元数据和文档内容的结构符合ES批量API的要求
内容的提问来源于stack exchange,提问作者helplessMax
相关产品推荐
相关产品推荐

