弹性搜索滚动(扫描)到Pandas DataFrame

时间:2018-07-23 09:43:09

标签: python pandas dataframe elasticsearch generator

我需要从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

1 个答案:

答案 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,您可以在双头队列中找到更多信息。