【发布时间】:2017-07-03 17:44:27
【问题描述】:
我想将一堆大型 pandas 数据帧(数百万行和 50 列)索引到 Elasticsearch 中。
在寻找有关如何执行此操作的示例时,大多数人将使用elasticsearch-py's bulk helper method,向其传递一个处理连接的实例of the Elasticsearch class,以及一个创建的字典列表with pandas' dataframe.to_dict(orient='records') method。元数据可以作为新列预先插入到数据框中,例如df['_index'] = 'my_index'等
但是,我有理由不使用 elasticsearch-py 库,并想直接与 Elasticsearch bulk API 交谈,例如通过requests 或其他方便的HTTP 库。此外,df.to_dict() 在大型数据帧上非常慢,不幸的是,将数据帧转换为字典列表,然后通过 elasticsearch-py 序列化为 JSON,听起来像dataframe.to_json() 这样的东西是不必要的开销,甚至相当快在大型数据帧上。
将 pandas 数据帧转换为批量 API 所需格式的简单快捷方法是什么?我认为朝着正确方向迈出的一步是使用dataframe.to_json(),如下所示:
import pandas as pd
df = pd.DataFrame.from_records([{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}])
df
a b
0 1 2
1 3 4
2 5 6
df.to_json(orient='records', lines=True)
'{"a":1,"b":2}\n{"a":3,"b":4}\n{"a":5,"b":6}'
现在这是一个换行符分隔的 JSON 字符串,但是它仍然缺少元数据。有什么方法可以让它进入那里?
编辑: 为了完整起见,元数据 JSON 文档应如下所示:
{"index": {"_index": "my_index", "_type": "my_type"}}
因此,最终批量 API 所期望的整个 JSON 看起来像 这(在最后一行之后有一个额外的换行符):
{"index": {"_index": "my_index", "_type": "my_type"}}
{"a":1,"b":2}
{"index": {"_index": "my_index", "_type": "my_type"}}
{"a":3,"b":4}
{"index": {"_index": "my_index", "_type": "my_type"}}
{"a":5,"b":6}
【问题讨论】:
-
您可以为您的示例 DF 发布预期的元数据吗?
-
好的,请看我的编辑。
-
我不理解那种格式(结构)——它不是有效的 JSON。你能做一个小测试,尝试使用它的批量 API 将这个小的“JSON”加载到 ElasticSearch 中吗?
-
是的,这确实不是有效的 JSON,而是多个有效 JSON 文档的换行符列表。不幸的是,this is what elasticsearch's bulk API expects。其背后的原因是批量数据在换行符处被拆分为文档,然后文档可能在文档实际被解析之前被转发到接收节点之外的其他节点。
标签: python pandas elasticsearch