通常,在ES中使用查詢時,預設返回的前10條結果,當我們一個查詢有上萬的結果時,我們如何擷取全部資料。。雖然我們可以通過size設定查詢後返回的條數。
ES的API中提供了scan和scroll,這個方法有點類型傳統資料庫中的遊標。
方法1:直接使用es提供的scroll
第一步:向ES伺服器發送如下GET請求。{}中的內容寫在請求體中。其中,scroll=1m,設定scroll 在1min內保持開啟狀態
GET /old_index/_search?scroll=10m
{
"query": { "match_all": {}},
"size": 1000
}
調用這個請求後,ES服務會響應一個類似以下的json:
{"_scroll_id":"c2NhbjszOzM1MTpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzM1MDpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzIzNzpnV2JCMkQ1RVFBdV90d3ZJOEVhOTl3OzE7dG90YWxfaGl0czo2NjUyOw==","took":3,"timed_out":false,"_shards":{"total":3,"successful":3,"failed":0},"hits":{"total":6652,"max_score":0.0,"hits":[]}}
,其中,_scroll_id在接下來的使用中非常重要,_scroll_id相當於傳統資料庫中的遊標對象。
第二步:向伺服器發送如下GET請求。將返回的_scroll_id作為參數傳給伺服器。第二行的內容是寫在請求體中。
GET /_search/scroll?scroll=1m
c2NhbjszOzM1MTpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzM1MDpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzIzNzpnV2JCMkQ1RVFBdV90d3ZJOEVhOTl3OzE7dG90YWxfaGl0czo2NjUyOw==
調用這個請求後,ES服務會響應一個類似以下的json:
{"_scroll_id":"c2NhbjszOzM1MTpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzM1MDpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzIzNzpnV2JCMkQ1RVFBdV90d3ZJOEVhOTl3OzE7dG90YWxfaGl0czo2NjUyOw==","took":2,"timed_out":false,"_shards":{"total":3,"successful":3,"failed":0},"hits":{"total":101,"max_score":null,"hits":[{"_index":"old_index","_type":"3","_id":"AVCoH6dlYbq5kuCt6S7A","_score":1.0,"_source":{文檔}},{"_index":"old_index","_type":"3","_id":"AVCoH6dlYbq5kuCt6S7A","_score":1.0,"_source":{文檔}}]}}
細心的我們會發現,ES返回的_scroll_id和發送給伺服器的的_scroll_id值相同。說明是同一個對象。
第三步:重複第二步,直到hits中的資料為空白。此時,該查詢的所有資料擷取完畢
第四步:刪除該_scroll_id。GET請求如下所示:
DELETE /_search/scroll
c2NhbjszOzM1MTpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzM1MDpvRkJrRHNWbFNiV2RPLVhlbWlYc1h3OzIzNzpnV2JCMkQ1RVFBdV90d3ZJOEVhOTl3OzE7dG90YWxfaGl0czo2NjUyOw==
注意:
The response to this scroll request includes the first batch of results. Although we specified a size of 1,000, we get back many more documents. When scanning, the size is applied to each shard, so you will get back a maximum of size * number_of_primary_shards documents in each batch.
方法2:使用python提供的helpers.scan方法
scan使用代碼:
scanResp = helpers.scan(es, _body, scroll= "10m", index= _index, doc_type= _doc_type, timeout="10m") for resp in scanResp: print resp