Elasticsearch Scroll 取出所有满足条件的数据

93 阅读1分钟

Elasticsearch Scroll 取出所有满足条件的数据

背景:es中每天3亿日志,需要通过日志生成一些报表出来,但是日志不能直接使用,需要对日志进行拆分重组,存储之后才能聚合。es查询结果默认最大是10000条,查询超过10000条的数据,无法通过分页查询查出来。

处理方法 :

1.调大max_result_window。

优点:只需要修改配置即可,代码不需要修改。

缺点:会大量消耗服务性能,影响查询效率,如果数据量剧增需要频繁调整该参数。

2.通过Scroll api 查询

话不多直接上代码

EsData struct {
        Host                 string `json:"host"`
        AccessTime           string `json:"access_time"`
}
func ScrollEsData(esQuery EsQuery) (res []*EsData) {
    res = make([]*EsData, 0)
    boolQuery := esQuery.GetBoolQuery().Must(elastic.NewMatchAllQuery())
​
    var scrollId string // 用于存储scroll ID的切片
    scroll := es.client.Scroll("index_name").
        Size(consts.EsMaxSize). // 每批取10000条
        Query(boolQuery)
​
    for {
        searchResult, err := scroll.Do(s.Ctx)
        if err == io.EOF {
            break // 没有更多的结果,退出循环
        }
        if err != nil {
            fmt.Println("scroll err:", err)
            break
        }
        for _, hit := range searchResult.Hits.Hits {
            tmp := new(EsData)
            err = json.Unmarshal(hit.Source, tmp) 
            if err != nil {
                fmt.Println("unmarshal err:%s", err)
                return
            }
            res = append(res, tmp)
        }
        scrollId = searchResult.ScrollId
    }
​
    _, err := es.client.ClearScroll().ScrollId(scrollId).Do(s.Ctx)
    if err != nil {
        log.Println("Failed to clear scroll ID %v: %v", scrollId, err)
    }
​
    return ipData
}