1. 程式人生 > >ElasticSearch查詢—分頁查詢詳解

ElasticSearch查詢—分頁查詢詳解

Elasticsearch中資料都儲存在分片中,當執行搜尋時每個分片獨立搜尋後,資料再經過整合返回。那麼,如何實現分頁查詢呢?

      按照一般的查詢流程來說,如果我想查詢前10條資料:

        1)客戶端請求發給某個節點

        2)節點轉發給個個分片,查詢每個分片上的前10條

        3)結果返回給節點,整合資料,提取前10條

        4)返回給請求客戶端

    那麼當我想要查詢第10條到第20條的資料該怎麼辦呢?這個時候就用到分頁查詢了。

    在ElasticSearch中實現分頁查詢的方式有兩種,分別為深度分頁(from-size)和快照分頁(scroll)

1.深度分頁(from-size)

  原理很簡單,就是查詢前20條資料,然後截斷前10條,只返回10-20的資料。這樣其實白白浪費了前10條的查詢。

    查詢API如下:

    {
       "from" : 0, "size" : 10,
        "query" : {
           "term" : { "user" : "kimchy" }
        }
     }

   其中,from定義了目標資料的偏移值,size定義當前返回的事件數目。預設from為0,size為10,即所有的查詢預設僅僅返回前10條資料。

     做過測試,越往後的分頁,執行的效率越低。

也就是說,分頁的偏移值越大,執行分頁查詢時間就會越長!

2. 快照分頁(scroll)

相對於from和size的分頁來說,使用scroll可以模擬一個傳統資料的遊標,記錄當前讀取的文件資訊位置。這個分頁的用法,不

是為了實時查詢資料,而是為了一次性查詢大量的資料(甚至是全部的資料)。因為這個scroll相當於維護了一份當前索引段的快照

資訊,這個快照資訊是你執行這個scroll查詢時的快照。在這個查詢後的任何新索引進來的資料,都不會在這個快照中查詢到。但是

它相對於from和size,不是查詢所有資料然後剔除不要的部分,而是記錄一個讀取的位置,保證下一次快速繼續讀取。

     查詢API如下:

   curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m' -d '
   {
        "query": {
             "match" : {
             "title" : "elasticsearch"
          }
       }
    }
      該查詢會自動返回一個_scroll_id,通過這個id(經過base64編碼)可以繼續查詢。
    curl -XGET  '叢集節點IP:9200/_search/scroll?scroll=1m&scroll_id=c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1'
3.java API實現
public class PageQueryInElasticSearch {

	private static String index = "test_index35";
	private static String type = "test_type35";
	public static void main(String[] args) {
	
		Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", "contentmanageres")
			    .put("client.transport.sniff", true)// 開啟ES嗅探功能,確保叢集連上多個節點
				.build();
		// 建立客戶端
		TransportClient transportClient = new TransportClient(settings);
		// 新增es的節點資訊,可以新增1個或多個
		TransportAddress transportAddress = new InetSocketTransportAddress("172.17.168.96", 9300);
		transportClient.addTransportAddresses(transportAddress);
		// 連線到的節點
		ImmutableList<DiscoveryNode> connectedNodes = transportClient.connectedNodes();
		for (DiscoveryNode discoveryNode : connectedNodes) {
			System.out.println(discoveryNode.getHostAddress());
		}
	
		System.out.println("from size 模式啟動!");
		Date begin = new Date();
		long count = transportClient.prepareCount(index).setTypes(type).execute().actionGet().getCount();//獲取所有記錄
		SearchRequestBuilder requestBuilder = transportClient.prepareSearch(index).setTypes(type).setQuery(QueryBuilders.matchAllQuery());
		for(int i=0,sum=0; sum<count; i++){
		    SearchResponse response = requestBuilder.setFrom(i).setSize(5000).execute().actionGet();
		    sum += response.getHits().hits().length;
		    System.out.println("總量"+count+" 已經查到"+sum);
		}
		Date end = new Date();
		System.out.println("耗時: "+(end.getTime()-begin.getTime()));
		
		
		System.out.println("scroll 模式啟動!");
		begin = new Date();
		SearchResponse scrollResponse = transportClient.prepareSearch(index)
		    .setSearchType(SearchType.SCAN)   //在ES 5.x版本中不存在SearchType.SCAN用法,可以用addSort(SortBuilders.fieldSort("_doc"))
		    .setSize(1000) //實際返回的數量為size*index的主分片個數(在ES 5.x版本中,返回的資料量就是引數中指定的資料量)
		    .setScroll(TimeValue.timeValueMinutes(1)) 
		    .execute().actionGet();  
		count = scrollResponse.getHits().getTotalHits();//獲取所有記錄,第一次不返回資料(在ES 5.x版本中,第一次有資料返回)
		for(int sum=0; sum<count; ){
		    scrollResponse = transportClient.prepareSearchScroll(scrollResponse.getScrollId())  
		        .setScroll(TimeValue.timeValueMinutes(8))  
		    .execute().actionGet();
		    sum += scrollResponse.getHits().hits().length;
		    System.out.println("總量"+count+" 已經查到"+sum);
		}
		end = new Date();
		System.out.println("耗時: "+(end.getTime()-begin.getTime()));

	}

}

相關連結如下:https://www.cnblogs.com/xing901022/archive/2016/03/16/5284902.html

                     http://www.jianshu.com/p/627887e3eea3

相關推薦

ElasticSearch查詢查詢

Elasticsearch中資料都儲存在分片中,當執行搜尋時每個分片獨立搜尋後,資料再經過整合返回。那麼,如何實現分頁查詢呢?       按照一般的查詢流程來說,如果我想查詢前10條資料:         1)客戶端請求發給某個節點         2)節點轉發給

SpringBoot 整合 Elasticsearch深度查詢

es 查詢共有4種查詢型別 QUERY_AND_FETCH:     主節點將查詢請求分發到所有的分片中,各個分片按照自己的查詢規則即詞頻文件頻率進行打分排序,然後將結果返回給主節點,主節點對所有資料進行彙總排序然後再返回給客戶端,此種方式只需要和es互動一次。       這種查詢方式存在資料量和排序問題,

MyBatis動態查詢,查詢,List/Array/Map查詢.

動態查詢 xml中程式碼 <select id="Selective" parameterType="com.***.***.entity.Doctor" resultMap="BaseResultMap"> sel

查詢&查詢

--子查詢 --把1個查詢結果在另一個查詢中使用,就叫做子查詢(把一個查詢語句做一個結果集使用) --查詢:班裡所有班號是4,並且姓飛的同學資訊 select * from Tbstudent where stuClassId=10 and stuName like '

Elasticsearch-IK詞器以及原始碼修改實現mysql熱更新

IK分詞器的安裝和使用 訪問ik分詞器github專案地址:https://github.com/medcl/elasticsearch-analysis-ik 1.在本地clone專案程式碼,git clone https://github.com/me

jQuery pagination示例

eval 顯示 索引 dev show jpg sum 把手 操作 前臺html ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Java Web開發jsp顯示高階效果

     許多網站都文章或其他類內容的分頁效果,初學者對於分頁的開發有時只會用程式碼,而沒有深入瞭解程式碼編寫前的業務邏輯結構,掌握好這個,我想,任何的效果的分頁都能自己解決……      1、確立jsp分頁的內部邏輯結構:        現在就採用標準MVC模式下的分頁做

spring data jpa bootstrap table 後端

關於spring data jpa 使用bootstrap table 分頁: 1.bootstrap table  js檔案程式碼: 2.controller中獲取前端分頁的資料: 3.service,需要注意pageabel的引數,這裡沒有使用sort排序方式,所

Django2.1中的功能

django的分頁功能類將我們常用的多種方法均封裝在Paginator類,根據這些方法我們均可深度定製我們的分頁功能。 首先來看看[Paginator] 類的構造方法: class Paginator(object_list, per_page, orphans=0, allow_empt

PHP演算法

所謂分頁顯示,也就是將資料庫中的結果集人為的分成一段一段的來顯示,這裡需要兩個初始 的引數:每頁多少條記錄($PageSize)? 當前是第幾頁($CurrentPageID)?現在只要再給我一個結果集,我就可以顯示某段特定的結果出來。 至於其他的引數,比如:上一頁($Pre

bootStrap-table 後臺

最近在學bootStrap ,學的我頭都大了,剛剛解決了個bootStrap的table的元件,就想來分享下,方便自己日後查閱,也看能不能讓你們學的輕鬆點。。 首先貼上官網的自誇: BootStrap Table是基於 Bootstrap 的 jQuery 表格外掛,通過簡

java實現技術

1.編寫通用的分頁工具 public class PageUtil { /*引數需要頁面傳入*/ private Integer pageSize=10;//每頁顯式多少條記錄 private Integer currentPage=1;//當前頁號 /*

JS實現HTML轉pdf(支援高清放大及

在這裡我主要講述實現思路及方法,原理大家可以自行百度,寫此文章主要是網上的很多實現方案都不能很好的支援高清放大及分頁。首先:引入三個js外掛,請自行上網百度下載,注意html2canvas.js版本太高會出現Promise未定義,本人猜測ES6高版本中可能用到ES6語法,請注

mybatis的關聯巢狀查詢--

問題描述 1. mybatis巢狀查詢後,分頁混亂:mybatis通過查詢結果之後摺疊結果集把資料放在了集合裡,這就導致總條數的混亂.而第一種的方式是分兩次查詢,分頁只針對第一次查詢,就不會有分頁的問題,所以解決方案就是把你的collection寫成第一種的方式 2. 摺疊結果集對映不上

Elasticsearch 6.x 的查詢數據

ef6 max div 6.2 info count clas table code { "size" :3, "query": { "match" : { "person_name" : "張老師"

elasticsearch 大資料場景下使用scroll實現查詢

es查詢大批量資料的”可能方案” 當使用es來請求大批量資料時,通常有三種辦法,其一:直接查詢獲取全量資料;其二:使用setFrom以及setSize解決;其三:使用es自帶的scroll分頁支援 方案評估 對於上述方案的評估,此處建議大家可以先看看這篇文章

聚合查詢越來越慢?——Elasticsearch的Global Ordinals與High Cardinality

  Elasticsearch中的概念很多,本文將從筆者在實踐過程中遇到的問題出發,逐步詳細介紹 Global Ordinals 和 High Cardinality ,這也是筆者的認知過程。文中的Elasticsearch 版本為5.5。 背景   故事是這樣

Elasticsearch——查詢From&Size VS scroll

主要有兩種方式 from/size from 偏移,預設為0 size 返回的結果數,預設為10 在資料量不大的情況下我們一般會使用from/size,而在深度分頁的情況下效率極低,該命令會把from+size條記錄全部加在到記憶體中,對結果返回前進行全域性

Elasticsearch的Java API/查詢/

Elasticsearch的Java API 新增Maven依賴。 連結到ES集 1.通過TransportClient這個介面,我們可以不啟動節點就可以和es叢集進行通訊,它需要指定es叢集中其中一

elasticsearch-利用遊標查詢 'Scroll'來做查詢

啟用遊標查詢可以通過在查詢的時候設定引數 scroll 的值為我們期望的遊標查詢的過期時間。 遊標查詢的過期時間會在每次做查詢的時候重新整理,所以這個時間只需要足夠處理當前批的結果就可以了,而不是處理查詢結果的所有文件的所需時間。 這個過期時間的引數很重要,因為保持這個遊標查詢視窗需要消耗資源,所以我們期望如