我需要从Elasticsearch
(es)获取大量数据,所以我使用的是scan
命令,它是对本机es scroll
命令的总结。
结果,我将获得以下生成器对象:<generator object scan at 0x000001BF5A25E518>
。而且,我想将所有数据插入Pandas
DataFrame
对象中,以便我可以轻松地处理它。
代码如下:
from elasticsearch import Elasticsearch
from elasticsearch.helpers import scan as escan
import pandas as pd
es = Elasticsearch(dpl_server, verify_certs=False)
body = {
"size": 1000,
"query": {
"match_all": {}
}
}
response = escan(client=es,
index="index-*,
query=body, request_timeout=30, size=1000)
print(response)
#<generator object scan at 0x000001BF5A25E518>
我要做的是将所有结果放入Pandas DataFrame中。如果我按如下所示打印生成器中的每个元素:
for res in response:
print(res['_source'])
# { .... }
# { .... }
# { .... }
我会收到很多字典。到目前为止,我的一个幼稚解决方案是像这样将它们一一添加:
df = None
for res in response:
if (df is None):
df = pd.DataFrame([res['_source']])
else:
df = pd.concat([df, pd.DataFrame([res['_source']])], sort=True)
我想知道是否有更好的方法(第一,在速度方面,第二,在简洁代码方面)。例如,最好将生成器的所有结果累加到一个列表中,然后构建完整的DataFrame
?
答案 0 :(得分:2)
您可以使用熊猫的json_normalize
。
from pandas.io.json import json_normalize
from elasticsearch import Elasticsearch
from elasticsearch.helpers import scan as escan
import pandas as pd
es = Elasticsearch(dpl_server, verify_certs=False)
body = {
"size": 1000,
"query": {
"match_all": {}
}
}
response = escan(client=es,
index="index",
query=body, request_timeout=30, size=1000)
# Initialize a double ended queue
output_all = deque()
# Extend deque with iterator
output_all.extend(response)
# Convert deque to DataFrame
output_df = json_normalize(output_all)
Here,您可以在双头队列中找到更多信息。