Go 程序利用 ElasticSearch 遊標 Scroll 實現海量數據分頁查詢

關注我的頭條號:@Wooola,10 年 Java 軟件開發及架構設計經驗,專注於 Java、Go 語言、微服務架構,致力於每天分享原創文章、快樂編碼和開源技術。

環境準備

  • ElasticSearch v6 集群環境
  • ES 第三方包
    1. github.com/olivere/elastic 文檔以及測試用例比 go-elasticsearch 豐富
    2. github.com/elastic/go-elasticsearch

    本文 olivere/elastic 包進行 es 開發。

    ElasticSearch 配置讀取

    編寫 conf.ini 配置文件,添加 elasticsearch 集群地址

    <code>[ES]
    EsAddrs = http://node1:9200,http://node2:9200,http://node3:9200/<code>

    定義 EsConf 結構體

    <code>EsConf struct {
    \t\tEsAddrs string
    }/<code>

    在 init 方法中,利用 goconfig

    讀取 confPath 參數指定的 conf.ini 配置文件路徑。

    <code>func init() {
    \tvar (
    \t\tiniF string
    \t)
    \tflag.StringVar(&iniF, "confPath", "d:/conf.ini", "Set Configuration File")
    \tflag.Parse()
    \tvar err error
    \tIniF, err = goconfig.LoadConfigFile(iniF)
    \tif err != nil {
    \t\tos.Exit(1)
    \t}
    \tlog.Println("Load conf.ini Success!")
    } /<code>

    在 main 方法中讀取 EsAddrs 參數值。

    <code>EsConf := &conf.EsConf{
    \t\tEsAddrs: GetStringValue(EsSection, EsAddrs, ""),
    \t}

    func GetStringValue(section string, key string, defValue string) (r string) {
    \tval, err := IniF.GetValue(section, key)
    \tif err != nil {
    \t\treturn defValue
    \t}
    \treturn val
    }/<code>

    初始化 elasticsearch 客戶端實例。

    <code>EsClient, err = NewClient()
    if err != nil {
    \t\tpanic(err)
    }

    func NewClient() (*elastic.Client, error) {
    \tesConf := EsConf
    \tif len(esConf.EsAddrs) == 0 {
    \t\tpanic("EsAddrs is Empty!")
    \t}

    \tesAddrs := strings.Split(esConf.EsAddrs, ",")
    \tclient, err := elastic.NewClient(elastic.SetURL(esAddrs...))
    \tlog.Println("ES initial successful!")
    \treturn client, err
    }/<code>

    ElasticSearch 遊標(Scroll)分頁

    時間查詢需求:

    <code>例如,查詢  到 /<code>

    對應 es 時間格式為:

    <code># 開始時間
    st := 20171027000000
    # 結束時間
    et :=20200328235959/<code>

    初始化遊標查詢,設置遊標每次查詢 size 大小:5000 條,注意 sort 排序時,必須是 字段 + .keyword,否則查詢會報錯。

    <code>boolQry := elastic.NewBoolQuery()
    boolQry.Must(elastic.NewRangeQuery("updateDate").From(st).To(et))
    res, err := EsClient.Scroll().Index(EsHisPendDB).Type(EsHisPendType).
    \t\t\tQuery(boolQry).
    \t\t\tSort("updateDate.keyword", false).
    \t\t\tScroll("5m").
    \t\t\tSize(Conf.ExpConf.ExpPageSize).
    \t\t\tDo(context.Background())

    # 抽取數據


    pendingList := extractPendList(*res.Hits)/<code>

    使用 for 循環讀取所有數據,直到 len(res.Hits.Hits) 大小為 0,說明 elasticsearch 查詢讀取完畢,停止 for 循環。

    <code>for {
    \t\t\tres, err := EsClient.Scroll("1m").ScrollId(scrollId).Do(context.TODO())\t\t
    \t\t\tpendingList := extractPendList(*res.Hits)\t\t\t
    }
    if len(res.Hits.Hits) <= 0 {
    \t\t\t\tbreak
    \t\t\t}/<code>

    輸出效果

    Go 程序利用 ElasticSearch 遊標 Scroll 實現海量數據分頁查詢

    其中使用 Scroll 遊標第一次查詢會產生 SrcollID 值。

    <code>DnF1ZXJ5VGhlbkZldGNoBQAAAAAABDKbFldaYi1nOUhBVF8yZHNfZkJISllSMEEAAAAAAAMrlhZMRWZNdVlNaFFiQ1pjdkFiNHBrMW1BAAAAAAAEMpwWV1piLWc5SEFUXzJkc19mQkhKWVIwQQAAAAAABDKdFldaYi1nOUhBVF8yZHNfZkJISllSMEEAAAAAAAMwQhY4YUFDNVNVNlJsRzc4NFVYRnRyZ2xB/<code>


    分享到:


    相關文章: