elasticsearch-py使用scan和scroll返回所有文档

22 投票
2 回答
29280 浏览
提问于 2025-04-18 01:45

我正在使用 elasticsearch-py 来连接我的 Elasticsearch 数据库,这个数据库里有超过 300 万个文档。我想把所有的文档都提取出来,以便进行数据处理并写入 CSV 文件。我用下面的代码轻松地获取了 10 个文档(默认返回的数量)。

es=Elasticsearch("glycerin")
query={"query" : {"match_all" : {}}}
response= es.search(index="_all", doc_type="patent", body=query)

for hit in response["hits"]["hits"]:
  print hit

不过,当我尝试使用扫描和滚动功能来获取所有文档时,遇到了一些问题。我尝试了两种不同的方法,但都没有成功。

方法一:

scanResp= es.search(index="_all", doc_type="patent", body=query, search_type="scan", scroll="10m")  
scrollId= scanResp['_scroll_id']

response= es.scroll(scroll_id=scrollId, scroll= "10m")
print response

在这里输入图片描述scroll/ 后,它给出了滚动 ID,然后以 ?scroll=10m (Caused by <class 'httplib.BadStatusLine'>: '')) 结束。

方法二:

query={"query" : {"match_all" : {}}}
scanResp= helpers.scan(client= es, query=query, scroll= "10m", index="", doc_type="patent", timeout="10m")

for resp in scanResp:
    print "Hiya"

如果在 for 循环之前打印出 scanResp,我得到的是 <generator object scan at 0x108723dc0>。因此,我相对确定我在滚动过程中搞错了什么,但不太清楚具体是哪里出了问题,也不知道该怎么修复。

结果:

在这里输入图片描述同样,在 scroll/ 后,它给出了滚动 ID,然后以 ?scroll=10m (Caused by <class 'httplib.BadStatusLine'>: '')) 结束。

我尝试增加传输类的最大重试次数,但这并没有改变什么。我非常希望能得到一些关于如何解决这个问题的建议。

注意:我的 Elasticsearch 在同一网络的远程桌面上。

2 个回答

2

你的问题解决了吗?

我有一个简单的解决办法,你每次调用滚动方法后,都必须更换一下 scroll_id,像下面这样:

response_tmp = es.scroll(scroll_id=scrollId, scroll= "1m")

scrollId = response_tmp['_scroll_id']
11

Python中的scan方法会向REST API发送一个GET请求。它试图通过HTTP发送你的scroll_id。这里最可能的情况是,你的scroll_id太大,无法通过HTTP发送,所以你看到这个错误,因为没有返回任何响应。

由于scroll_id的大小是根据你拥有的分片数量而增长的,因此使用POST请求,并将scroll_id作为JSON的一部分发送会更好。这样可以避免因为太大而无法进行HTTP调用的问题。

撰写回答