问题: 工作中,需要将Elasticsearch中几千万的数据下载到本地磁盘中,
1. 先借助游标,将所有结果数据存储到内存中
2. 然后将内存中结果数据写入到磁盘,也就是文件中
3. 因为几千万条数据过大,所以我们在处理的时候就需要先将缓存在内存中的数据写入到磁盘中,然后将缓存清空,继续读取下一段数据(我们在写入到磁盘中需要注意不能覆盖之前写的文件,选择模式应该是追加读写)
解决:
import csv
from elasticsearch import Elasticsearch
es = Elasticsearch(hosts="218.22.29.213", port=59200, timeout=200)
# 1. 先借助游标,将所有结果数据存储到内存中
# 2. 然后将内存中的结果数据写入到磁盘,也就是文件中
query1 = {
"size": 10000
}
query = es.search(index="passdata_20190318", doc_type="epolice", scroll='5m', body=query1)
value = query["hits"]["hits"]
# es查询出的结果第一页
results = query['hits']['hits']
# es查询出的结果总量
total = query['hits']['total']
# 游标用于输出es查询出的所有结果
scroll_id = query['_scroll_id']
# 在发送查询请求的时候,就告诉ES需要使用游标,并定义每次返回数据量的大小
# 定义一个list变量results用来存储数据结果,在代码中,可以另其为空list,即results=[],也可以先将返回结果
# 的第一页存尽进来, 即results = query['hits']['hits']
# 对于所有二级结果数据写个分页加载到内存变量的循环
task = 1
for i in range(0, int(total / 100) + 1):
# scroll参数必须制定否则会报错
query_scroll = es.scroll(scroll_id=scroll_id, scroll="5m")['hits']['hits']
results += query_scroll
# 导出到Excel文件中
# 下述函数模式有(1. 文件名 ,mode 模式)
# -- w write,r ride ,a append
# 1. w 只能操作写入 r 只能读取 a向文件追加
# 2. w+ 只读可写 r+ 可读可写 a+可读可追加
# 3. wb+ 写入进制数据
# 4. w模式打开文件,如果文件中有数据,再次写入内容,会把原来的覆盖掉
# 我们这里需要保留之前写入的数据,所以模式选择的是'a+'可读可追加
with open("D://ml/passdata_20190318.csv", 'a+', newline='', encoding="utf-8") as flow:
# 获取_source 下的所有字段名
names = results[0]['_source'].keys()
csv_writer = csv.writer(flow)
csv_writer.writerow(names)
for res in results:
csv_writer.writerow(res['_source'].values())
# 将内存中的数据冲刷到文件中
flow.flush()
results = []
print("done!" + "---" + str(task))
task += 1
# # 导出到txt文本中
# file_handle = open("D://ml/data.txt", 'w', newline='', encoding="gbk")
# # 上述函数模式有(1. 文件名 ,mode 模式)
# # 1. w 只能操作写入 r 只能读取 a向文件追加
# # 2. w+ 只读可写 r+ 可读可写 a+可读可追加
# # 3. wb+ 写入进制数据
# # 4. w模式打开文件,如果而文件中有数据,再次写入内容,会把原来的覆盖掉
#
# for res in results:
# file_handle.write(str(res['_source'].values()))
# file_handle.write("\r\n")