python 使用elasticsearch 實(shí)現(xiàn)翻頁(yè)的三種方式
使用ES做搜索引擎拉取數(shù)據(jù)的時(shí)候,如果數(shù)據(jù)量太大,通過(guò)傳統(tǒng)的from + size的方式并不能獲取所有的數(shù)據(jù)(默認(rèn)最大記錄數(shù)10000),因?yàn)殡S著頁(yè)數(shù)的增加,會(huì)消耗大量的內(nèi)存,導(dǎo)致ES集群不穩(wěn)定。因此延伸出了scroll,search_after等翻頁(yè)方式。
一、from + size 淺分頁(yè)
"淺"分頁(yè)可以理解為簡(jiǎn)單意義上的分頁(yè)。它的原理很簡(jiǎn)單,就是查詢(xún)前20條數(shù)據(jù),然后截?cái)嗲?0條,只返回10-20的數(shù)據(jù)。這樣其實(shí)白白浪費(fèi)了前10條的查詢(xún)。
GET test/_search { "query": { "bool": { "filter": [ { "term": { "age": 28 } } ] } }, "size": 10, "from": 20, "sort": [ { "timestamp": { "order": "desc" }, "_id": { "order": "desc" } } ] }
from定義了目標(biāo)數(shù)據(jù)的偏移值,size定義當(dāng)前返回的數(shù)目。默認(rèn)from為0,size為10,即所有的查詢(xún)默認(rèn)僅僅返回前10條數(shù)據(jù)。
在這里有必要了解一下from/size的原理:
因?yàn)閑s是基于分片的,假設(shè)有5個(gè)分片,from=100,size=10。則會(huì)根據(jù)排序規(guī)則從5個(gè)分片中各取回100條數(shù)據(jù)數(shù)據(jù),然后匯總成500條數(shù)據(jù)后選擇最后面的10條數(shù)據(jù)。
做過(guò)測(cè)試,越往后的分頁(yè),執(zhí)行的效率越低??傮w上會(huì)隨著from的增加,消耗時(shí)間也會(huì)增加。而且數(shù)據(jù)量越大,就越明顯!
二、scroll 深分頁(yè)
from+size查詢(xún)?cè)?0000-50000條數(shù)據(jù)(1000到5000頁(yè))以?xún)?nèi)的時(shí)候還是可以的,但是如果數(shù)據(jù)過(guò)多的話(huà),就會(huì)出現(xiàn)深分頁(yè)問(wèn)題。為了解決上面的問(wèn)題,elasticsearch提出了一個(gè)scroll滾動(dòng)的方式。
scroll 類(lèi)似于sql中的cursor,使用scroll,每次只能獲取一頁(yè)的內(nèi)容,然后會(huì)返回一個(gè)scroll_id。根據(jù)返回的這個(gè)scroll_id可以不斷地獲取下一頁(yè)的內(nèi)容,所以scroll并不適用于有跳頁(yè)的情景。
# -*- coding: utf-8 -*- # @Time : # @Author : from elasticsearch import Elasticsearch es = Elasticsearch(hosts="ip:9200", timeout=20, max_retries=10, retry_on_timeout=True) # Elasticsearch 需要保持搜索的上下文環(huán)境多久 游標(biāo)查詢(xún)過(guò)期時(shí)間為10分鐘(10m) page = es.search( index="source_keyword_message", doc_type="source_keyword_message", scroll='10m', size=100, body={ "query": {"match_all": {}}, } ) # 游標(biāo)用于輸出es查詢(xún)出的所有結(jié)果 sid = page['_scroll_id'] # es查詢(xún)出的結(jié)果總量 scroll_size = page['hits']['total'] # es查詢(xún)出的結(jié)果第一頁(yè) datas = page.get('hits').get('hits') while (scroll_size > 0): page = es.scroll(scroll_id=sid, scroll='5m') sid = page['_scroll_id'] scroll_size = len(page['hits']['hits']) datas = page.get('hits').get('hits')
- scroll=5m表示設(shè)置scroll_id保留5分鐘可用。
- 使用scroll必須要將from設(shè)置為0。默認(rèn)0
- size決定后面每次調(diào)用_search搜索返回的數(shù)量
三、search_after 深分頁(yè)
scroll 的方式,官方的建議不用于實(shí)時(shí)的請(qǐng)求(一般用于數(shù)據(jù)導(dǎo)出),因?yàn)槊恳粋€(gè) scroll_id 不僅會(huì)占用大量的資源,而且會(huì)生成歷史快照,對(duì)于數(shù)據(jù)的變更不會(huì)反映到快照上。
search_after 分頁(yè)的方式是根據(jù)上一頁(yè)的最后一條數(shù)據(jù)來(lái)確定下一頁(yè)的位置,同時(shí)在分頁(yè)請(qǐng)求的過(guò)程中,如果有索引數(shù)據(jù)的增刪改查,這些變更也會(huì)實(shí)時(shí)的反映到游標(biāo)上。但是需要注意,因?yàn)槊恳豁?yè)的數(shù)據(jù)依賴(lài)于上一頁(yè)最后一條數(shù)據(jù),所以無(wú)法跳頁(yè)請(qǐng)求。
為了找到每一頁(yè)最后一條數(shù)據(jù),每個(gè)文檔必須有一個(gè)全局唯一值,官方推薦使用 _uid 作為全局唯一值,其實(shí)使用業(yè)務(wù)層的 id 也可以。
GET test/_search { "query": { "bool": { "filter": [ { "term": { "age": 28 } } ] } }, "size": 20, "from": 0, "sort": [ { "timestamp": { "order": "desc" }, "_id": { "order": "desc" } } ] }
- 使用search_after必須要設(shè)置from=0。
- 這里我使用timestamp和_id作為唯一值排序。
- 我們?cè)诜祷氐淖詈笠粭l數(shù)據(jù)里拿到sort屬性的值傳入到search_after。
使用sort返回的值搜索下一頁(yè):
GET test/_search { "query": { "bool": { "filter": [ { "term": { "age": 28 } } ] } }, "size": 10, "from": 0, "search_after": [ 1541495312521, "d0xH6GYBBtbwbQSP0j1A" ], "sort": [ { "timestamp": { "order": "desc" }, "_id": { "order": "desc" } } ] }
到此這篇關(guān)于python 使用elasticsearch 實(shí)現(xiàn)翻頁(yè)的三種方式的文章就介紹到這了,更多相關(guān)python elasticsearch 翻頁(yè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python實(shí)戰(zhàn)之Elasticsearch的高級(jí)實(shí)現(xiàn)詳解
- python中的elasticsearch_dsl查詢(xún)語(yǔ)句轉(zhuǎn)換成es查詢(xún)語(yǔ)句詳解
- python中elasticsearch_dsl模塊的使用方法
- Python操作Elasticsearch處理timeout超時(shí)
- python3實(shí)現(xiàn)elasticsearch批量更新數(shù)據(jù)
- python更新數(shù)據(jù)庫(kù)中某個(gè)字段的數(shù)據(jù)(方法詳解)
- Python更新數(shù)據(jù)庫(kù)腳本兩種方法及對(duì)比介紹
- Python調(diào)用Elasticsearch更新數(shù)據(jù)庫(kù)的操作方法
相關(guān)文章
在Python中畫(huà)圖(基于Jupyter notebook的魔法函數(shù))
這篇文章主要介紹了在Python中畫(huà)圖(基于Jupyter notebook的魔法函數(shù)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Django項(xiàng)目實(shí)戰(zhàn)之配置文件詳解
這篇文章主要給大家介紹了關(guān)于Django項(xiàng)目實(shí)戰(zhàn)之配置文件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5訪問(wèn)系統(tǒng)剪切板QClipboard類(lèi)詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5訪問(wèn)系統(tǒng)剪切板QClipboard類(lèi)詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-02-02wxpython實(shí)現(xiàn)圖書(shū)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了wxpython實(shí)現(xiàn)圖書(shū)管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03Python實(shí)現(xiàn)字典去除重復(fù)的方法示例
這篇文章主要介紹了Python實(shí)現(xiàn)字典去除重復(fù)的方法,涉及Python字典遍歷、文件讀取、去除重復(fù)等相關(guān)操作技巧,需要的朋友可以參考下2017-07-07