Go操作elasticsearch合集

安装ES集群(Liunx版本)

参考链接这个博主的很不错

连接客户端

案例

// 连接Es
func connectEs() (*elastic.Client, error) {
	return elastic.NewClient(
		// 设置Elastic服务地址
		elastic.SetURL("http://192.168.6.39:9201"),
		// 允许指定弹性是否应该定期检查集群,默认为true,会把请求http://ip:port/_nodes/http,
		// 并将其返回的publish_address作为请求路径
		//elastic.SetSniff(true),
		// 心跳检查,间隔时间
		elastic.SetHealthcheckInterval(time.Second*5),
		// 设置错误日志
		elastic.SetErrorLog(log.New(os.Stderr, "ES-ERROR ", log.LstdFlags)),
		// 设置info日志
		elastic.SetInfoLog(log.New(os.Stdout, "ES-INFO ", log.LstdFlags)),
	)
}

简单的一些查看操作

func TestBeego(t *testing.T) {
	client, err := connectEs()
	if err != nil {
		t.Error(err)
		return
	}
	// 健康检查
	Health, _ := client.ClusterHealth().Index().Do(context.TODO())
	// 查看索引
	Indexs, _ := client.CatIndices().Do(context.TODO())
	// 模糊查询某个索引
	Index, _ := client.CatIndices().Index(".apm*").Do(context.TODO())
	// 查看所有分片
	Nodes, _ := client.CatAllocation().Do(context.TODO())
	// 查看谁是主分片
	MasterNode, _ := client.CatMaster().Do(context.TODO())
	fmt.Println("健康检查: ", Health)
	fmt.Println("索引: ", Indexs)
	fmt.Println("查看所有分片: ", Nodes)
	fmt.Println("查看谁是主分片: ", MasterNode)
	fmt.Println("模糊查看索引 : ", Index)

}

索引基础操作CRUD

创建索引

const indexName = "user_test"

// 创建索引 (自己指定mapping)
func TestCreateIndexMapping(t *testing.T) {
	userMapping := `{
    "mappings":{
        "properties":{
            "name":{
                "type":"keyword"
            },
            "age":{
                "type":"byte"
            },
            "birth":{
                "type":"date"
            }
        }
    }
}`
	// 获取客户端
	client, _ := connectEs()
	// 检索当前有没有该索引

	exist, err := client.IndexExists(indexName).Do(context.Background())
	if err != nil {
		t.Errorf("检测索引失败:%s", err)
		return
	}
	if exist {
		t.Error("索引已经存在,无需重复创建!")
		return
	}
	// 不存在就创建
	//	如果想直接创建索引,只需删除BodyString(userMapping)
	res, err := client.CreateIndex(indexName).BodyString(userMapping).Do(context.Background())
	if err != nil {
		t.Errorf("创建索引失败:%s", err)
		return
	}
	fmt.Println("创建成功: ", res)
}

添加数据(单条数据)

/ 添加数据(单条添加)
type UserInfo struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Birth string `json:"birth"`
}

func TestAddOne(t *testing.T) {
	client, _ := connectEs()
	// 创建userInfo
	userInfo := UserInfo{
		Age:   18,
		Name:  "冯消水",
		Birth: "2000-01-15",
	}
	// 这里可以选择指定或者不指定 Id 不指定ID 就会用默认的
	response, err := client.Index().Index(indexName).Id("1").BodyJson(userInfo).Do(context.Background())
	if err != nil {
		t.Errorf("添加失败:%s", err)
	}
	fmt.Println("添加成功", response)
}

在这里插入图片描述

批量添加

// 批量添加
func TestBatchAdd(t *testing.T) {
	client, _ := connectEs()
	userMap := make(map[string]string)
	userMap["fjj"] = "2000-01-02"
	userMap["mjd"] = "2000-02-02"
	userMap["liu"] = "2000-03-02"
	userMap["admin"] = "2000-04-02"
	rand.Seed(time.Now().Unix())
	// 创建bulk
	bulkService := client.Bulk().Index(indexName)
	id := 2
	for name, birth := range userMap {
		userinfos := UserInfo{
			Age:   rand.Intn(50),
			Name:  name,
			Birth: birth,
		}
		// 批量添加
		doc := elastic.NewBulkCreateRequest().Id(strconv.Itoa(id)).Doc(userinfos)
		bulkService.Add(doc)
		id++
	}
	// 检查添加的数据是否为空
	if bulkService.NumberOfActions() < 1 {
		t.Error("被添加的数据不能为空!")
		return
	}
	// 保存
	response, err := bulkService.Do(context.Background())
	if err != nil {
		t.Errorf("保存失败:%s", err)
		return
	}
	fmt.Println("保存成功: ", response)
}

通过id 修改数据


// 修改数据(script) 根据id更新
func TestUpdateOneByScript(t *testing.T) {
	client, _ := connectEs()
	// 通过id 修改
	updateResponse, err := client.Update().Index(indexName).Id("1").Script(elastic.NewScript("ctx._source.birth='2099-12-31'")).Do(context.Background())
	if err != nil {
		t.Errorf("根据ID更新单条记录失败:%s", err)
		return
	}
	fmt.Println("根据ID更新成功:", updateResponse.Result)
}

根据条件更新

// 根据条件更新
func TestUpdate(t *testing.T) {
	client, _ := connectEs()
	res, err := client.UpdateByQuery(indexName).Query(elastic.NewTermQuery("name", "mjd")).Script(elastic.NewScript("ctx._source.birth='2099-12-31'")).ProceedOnVersionConflict().Do(context.Background())
	if err != nil {
		t.Errorf("根据条件更新单条记录失败:%s", err)
		return
	}
	fmt.Println("根据条件更新成功:", res.Updated)
}

多字段更新

// 多字段更新
func TestUpdateByDoc(t *testing.T) {
	client, _ := connectEs()
	response, err := client.Update().Index(indexName).Id("2").Doc(map[string]interface{}{
		"name": "mjd2", "age": 39,
	}).Do(context.Background())
	if err != nil {
		t.Errorf("更新记录失败:%s", err)
		return
	}
	fmt.Println("根据条件更新成功:", response.Result)
}

批量更新

func TestBatchUpdate(t *testing.T) {
	client, _ := connectEs()
	bulkService := client.Bulk().Index(indexName)
	for _, id := range []string{"1", "2", "3", "4", "5"} {
		doc := elastic.NewBulkUpdateRequest().Id(id).Doc(map[string]interface{}{"age": 18})
		bulkService.Add(doc)
	}
	// 被更新的数量不能小于0
	if bulkService.NumberOfActions() < 0 {
		t.Error("被更新的数量不能为空")
		return
	}
	// 执行操作
	do, err := bulkService.Do(context.Background())
	if err != nil {
		t.Errorf("批量更新失败:%v", err)
		return
	}
	fmt.Println("更新成功:", do.Updated())
}

删除

// 通过Id 删除
func TestDelById(t *testing.T) {
	client, _ := connectEs()
	response, err := client.Delete().Index(indexName).Id("cxDhC4YBndr2knWC-YJt").Do(context.Background())
	if err != nil {
		t.Errorf("删除失败:%s", err)
		return
	}
	fmt.Println("删除成功: ", response.Result)
}

根据条件删除

// 根据条件删除
func TestDelByWhere(t *testing.T) {
	client, _ := connectEs()
	scrollResponse, err := client.DeleteByQuery(indexName).Query(elastic.NewTermQuery("name", "mjd")).ProceedOnVersionConflict().Do(context.Background())
	if err != nil {
		t.Errorf("删除失败:%s", err)
		return
	}
	fmt.Println("删除成功: ", scrollResponse.Deleted)
}

索引简单查询及其花式查询

单条查询

// 单条查询
func TestSearchOneEs(t *testing.T) {
	client, _ := connectEs()
	getResult, err := client.Get().Index(indexName).Id("1").Do(context.Background())
	if err != nil {
		t.Errorf("获取失败: %s", err)
		return
	}
	// 把查出来的结果json
	json, _ := getResult.Source.MarshalJSON()
	fmt.Printf("查询单条结果:%s \n", json)
}

批量查询

func TestSearchMoreEs(t *testing.T) {
	client, _ := connectEs()
	searchResult, err := client.Search(indexName).Query(elastic.NewMatchQuery("age", 18)).From(0).Size(10).Pretty(true).Do(context.Background())
	if err != nil {
		t.Errorf("获取失败: %s", err)
		return
	}
	// 创建集合 用来存放
	var userList []UserInfo
	for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
		tmp := i.(UserInfo)
		userList = append(userList, tmp)
	}
	fmt.Printf("查询结果:%v\n", userList)
}

精确匹配单个字段

func TestSearchByWhere(t *testing.T) {
	client, _ := connectEs()
	// 创建term
	termQuery := elastic.NewTermQuery("age", 18)
	searchResult, err := client.Search().
		// 设置索引名
		Index(indexName).
		// 设置查询条件
		Query(termQuery).
		// 设置排序字段 false 是逆序
		Sort("birth", true).
		// 分页参数
		From(0).Size(10). //设置每页的大小
		Pretty(true).     // 查询结果返回JSON格式
		// 执行请求
		Do(context.Background())
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}
}

通过terms 实现Sql的in查询


// 通过terms 实现Sql  in 查询
func TestSearchByIn(t *testing.T) {
	client, _ := connectEs()
	termsQuery := elastic.NewTermsQuery("name", "mjd", "fjj")
	searchResult, err := client.Search().
		// 设置索引名
		Index(indexName).
		// 设置查询条件
		Query(termsQuery).
		// 设置排序字段 false 是逆序
		Sort("birth", true).
		// 分页参数
		From(0).Size(10). //设置每页的大小
		Pretty(true).     // 查询结果返回JSON格式
		// 执行请求
		Do(context.Background())
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}
}

范围查询 类似于 某个值 >‘xx’ and 某个值 < ‘xxx’

// 范围查询
func TestSearchByRange(t *testing.T) {
	client, _ := connectEs()
	// >  <
	//elastic.NewRangeQuery("age").Gt("19").Lt("20")
	// >=  <=
	rangeQuery := elastic.NewRangeQuery("age").Gte("18").Lte("20")
	searchResult, err := client.Search().Index(indexName).Query(rangeQuery).Do(context.Background())
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}

}

bool 组合查询

must 条件

// bool 组合查询
// 1 must 条件
func TestSearchMust(t *testing.T) {
	client, _ := connectEs()
	boolQuery := elastic.NewBoolQuery()
	// 创建term
	termQuery := elastic.NewTermQuery("name", "fjj")
	matchQuery := elastic.NewMatchQuery("age", 18)

	// 设置bool查询的must条件, 组合了两个子查询
	// 表示搜索匹配name=fjj且age匹配18
	boolQuery.Must(termQuery, matchQuery)

	searchResult, err := client.Search().
		Index(indexName).        // 设置索引名
		Query(boolQuery).        // 设置查询条件
		From(0).                 // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).                // 设置分页参数 - 每页大小
		Do(context.Background()) // 执行请求
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}

}

must_not

// must_not
func TestSearchMustNot(t *testing.T) {
	client, _ := connectEs()
	// 创建bool
	boolQuery := elastic.NewBoolQuery()
	// 创建term
	termQuery := elastic.NewTermQuery("age", 18)
	// 设置条件
	query := boolQuery.MustNot(termQuery)
	searchResult, err := client.Search().Index(indexName).Query(query).Do(context.Background())
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}
}

should 条件

// should 类似与OR
func TestSearchShould(t *testing.T) {
	client, _ := connectEs()
	// 创建bool查询
	boolQuery := elastic.NewBoolQuery().Must()

	// 创建term
	termQuery := elastic.NewTermQuery("name", "fjj")
	matchQuery := elastic.NewMatchQuery("age", 18)

	// 设置bool查询的should条件, 组合了两个子查询
	// 表示搜索匹配name=fjj且age匹配18
	boolQuery.Should(termQuery, matchQuery)
	searchResult, err := client.Search().
		Index(indexName).        // 设置索引名
		Query(boolQuery).        // 设置查询条件
		From(0).                 // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).                // 设置分页参数 - 每页大小
		Do(context.Background()) // 执行请求
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	if searchResult.TotalHits() > 0 {
		// 创建集合 用来存放
		var userList []UserInfo
		for _, i := range searchResult.Each(reflect.TypeOf(UserInfo{})) {
			tmp := i.(UserInfo)
			userList = append(userList, tmp)
		}
		fmt.Printf("查询结果:%v\n", userList)
	}
}

索引操作 聚合/桶操作

count 操作


// count 聚合
func TestTermsCount(t *testing.T) {
	// 链接客户端
	client, _ := connectEs()
	//获取提供上下文对象
	ctx := context.Background()
	// 创建value count 指标聚合
	countAggregation := elastic.NewValueCountAggregation().Field("age")
	searchResult, err := client.Search().Index(indexName). // 索引名
								Query(elastic.NewMatchAllQuery()).      // 设置搜索条件
								Aggregation("total", countAggregation). // 设置聚合条件,并为聚合条件设置一个名字,支持添加多个聚合条件,命名不一样即可。
								Size(0).                                // 分页
								Do(ctx)
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	// 使用ValueCount函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.ValueCount("total")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

类似SQL的count(DISTINCT 字段)用法。

func TestCountDistinct(t *testing.T) {
	// 链接客户端
	client, _ := connectEs()
	// 设置指标聚合
	cardinalityAggregation := elastic.NewCardinalityAggregation().Field("age")
	// 设置搜索条件
	searchResult, err := client.Search().
		Index("kibana_sample_data_flights").          // 设置索引名
		Query(elastic.NewMatchAllQuery()).            // 设置查询条件
		Aggregation("total", cardinalityAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0).                                      // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background())                      // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Cardinality函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Cardinality("total")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

Avg

// Avg
func TestAvg(t *testing.T) {
	client, _ := connectEs()
	// 创建 Avg 指标聚合
	avgAggregation := elastic.NewAvgAggregation().Field("age")
	searchResult, err := client.Search().
		Index(indexName).                         // 设置索引名
		Query(elastic.NewMatchAllQuery()).        // 设置查询条件
		Aggregation("avg_price", avgAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0).                                  // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background())                  // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Avg函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Avg("avg_price")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

Sum

// sum
func TestSum(t *testing.T) {
	client, _ := connectEs()
	// 创建Sum 聚合
	sumAggregation := elastic.NewSumAggregation().Field("age")
	searchResult, err := client.Search().
		Index(indexName).                           // 设置索引名
		Query(elastic.NewMatchAllQuery()).          // 设置查询条件
		Aggregation("total_price", sumAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0).                                    // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background())                    // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Sum函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Sum("total_price")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

Max

// Max
func TestMax(t *testing.T) {
	client, _ := connectEs()
	// 设置Max指标聚合
	newMaxAggregation := elastic.NewMaxAggregation().Field("age")
	searchResult, err := client.Search().
		Index(indexName). // 设置索引名
		Query(elastic.NewMatchAllQuery()). // 设置查询条件
		Aggregation("max_price", newMaxAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0). // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background()) // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Max函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Max("max_price")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

Min

func TestMin(t *testing.T) {
	client, _ := connectEs()
	// 设置min
	newMaxAggregation := elastic.NewMaxAggregation().Field("age")

	searchResult, err := client.Search().
		Index(indexName).                            // 设置索引名
		Query(elastic.NewMatchAllQuery()).           // 设置查询条件
		Aggregation("min_price", newMinAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0).                                     // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background())                     // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Min函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Min("min_price")
	if found {
		// 打印结果,注意:这里使用的是取值运算符
		fmt.Println(*agg.Value)
	}
}

聚合terms

// 聚合查询 terms
func TestTermsAggregation(t *testing.T) {
	// 链接客户端
	client, _ := connectEs()
	// 先通过名字分组
	termsAggregation := elastic.NewTermsAggregation().Field("name").Size(10).OrderByCountDesc()
	// 再通过生日中的年分组
	histogramAggregation := elastic.NewDateHistogramAggregation().Field("birth").CalendarInterval("year")
	// 设置嵌套聚合查询 意思先按照名字分组 ,在把名字分好组的通过生日字段中的年来分组。等于做了两次分组
	termsAggregation = termsAggregation.SubAggregation("histogramAggregation", histogramAggregation)
	// ES 查询
	searchResult, err := client.Search().
		Index(indexName).                                  // 索引名
		Query(elastic.NewMatchAllQuery()).                 // 设置查询条件
		Aggregation("termsAggregation", termsAggregation). // 设置聚合条件 需要给聚合设置一个名字
		Pretty(true).Do(context.Background())              // 返回可读的json
	if err != nil {
		t.Errorf("查询失败:%s", err)
		return
	}
	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())
	// 遍历ES查询结果,因为首先使用的是terms聚合条件,
	// 所以查询结果先使用Terms函数和聚合条件的名字读取结果。
	bucketKeyItems, b := searchResult.Aggregations.Terms("termsAggregation")
	// 判断聚合结果是否为空
	if !b {
		// 没有查询到terms聚合结果
		fmt.Printf("we should have a terms aggregation called %q", "termsAggregation")
	}
	// 遍历桶数据
	for _, bucket := range bucketKeyItems.Buckets {
		// 每个桶都有一个key值 类似于 group by 的值
		user := bucket.Key
		// 查询嵌套聚合查询的数据
		// 因为我们使用的是Date histogram聚合,所以需要使用DateHistogram函数和聚合名字获取结果
		histogram, found := bucket.DateHistogram("histogramAggregation")
		if found {
			// 如果找到Date histogram聚合结果,则遍历桶数据
			for _, year := range histogram.Buckets {
				var key string
				if s := year.KeyAsString; s != nil {
					// 因为返回的是指针类型,这里做一下取值运算
					key = *s
				}
				// 打印结果
				fmt.Printf("user %q has %d tweets in %q\n", user, year.DocCount, key)
			}
		}
	}
}

Histogram聚合

func TestHistogram(t *testing.T) {
	client, _ := connectEs()
	// 创建Histogram 桶
	aggregation := elastic.NewHistogramAggregation().
		Field("age"). // 根据那个字段分组
		Interval(50)  // 分桶的间隔是50 意思就是age 字段值按照50间隔分组

	searchResult, err := client.Search().Index(indexName).Query(elastic.NewMatchAllQuery()). // 设置搜索条件
													Aggregation("age", aggregation).Size(0).Do(context.Background())
	if err != nil {
		// Handle error
		panic(err)
	}
	// 使用Histogram函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Histogram("age")
	if !found {
		log.Fatal("没有找到聚合数据")
	}

	// 遍历桶数据
	for _, bucket := range agg.Buckets {
		// 每一个桶都有一个key值,其实就是分组的值,可以理解为SQL的group by值
		bucketValue := bucket.Key

		// 打印结果, 默认桶聚合查询,都是统计文档总数
		fmt.Printf("bucket = %q 文档总数 = %d\n", bucketValue, bucket.DocCount)
	}
}

DateHistogram聚合


func TestDateHistogram(t *testing.T) {
	client, _ := connectEs()
	// 创建DateHistogram聚合
	histogramAggregation := elastic.NewDateHistogramAggregation().Field("birth").
		// 根据date字段值,对数据进行分组
		//  分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
		CalendarInterval("month").
		// 设置返回结果中桶key的时间格式
		Format("yyyy-MM-dd")
	searchResult, err := client.Search().
		Index(indexName).                                     // 设置索引名
		Query(elastic.NewMatchAllQuery()).                    // 设置查询条件
		Aggregation("sales_over_time", histogramAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0).                                              // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background())                              // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用DateHistogram函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.DateHistogram("sales_over_time")
	if !found {
		log.Fatal("没有找到聚合数据")
	}

	// 遍历桶数据
	for _, bucket := range agg.Buckets {
		// 每一个桶都有一个key值,其实就是分组的值,可以理解为SQL的group by值
		bucketValue := bucket.Key

		// 打印结果, 默认桶聚合查询,都是统计文档总数
		fmt.Print("bucket = 文档总数 = ", bucketValue, bucket.DocCount)
	}
}

Range 聚合

func TestRange(t *testing.T) {
	client, _ := connectEs()
	// 设置 range 桶
	rangeAggregation := elastic.NewRangeAggregation().Field("age"). // 根据age字段分桶
		AddUnboundedFrom(30). // 范围配置, 0 - 30
		AddRange(30.0, 40.0). // 范围配置,30-40
		AddUnboundedTo(40.0) // 范围配置,> 200的值
	searchResult, err := client.Search().
		Index(indexName). // 设置索引名
		Query(elastic.NewMatchAllQuery()). // 设置查询条件
		Aggregation("price_ranges", rangeAggregation). // 设置聚合条件,并为聚合条件设置一个名字
		Size(0). // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(context.Background()) // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	// 使用Range函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Range("price_ranges")
	if !found {
		log.Fatal("没有找到聚合数据")
	}

	// 遍历桶数据
	for _, bucket := range agg.Buckets {
		// 每一个桶都有一个key值,其实就是分组的值,可以理解为SQL的group by值
		bucketValue := bucket.Key

		// 打印结果, 默认桶聚合查询,都是统计文档总数
		fmt.Printf("bucket = %q 文档总数 = %d\n", bucketValue, bucket.DocCount)
	}
}

嵌套聚合的用法

任意聚合类型都支持嵌套,桶聚合可以嵌套桶聚合,也可以嵌套指标聚合。

例子:

// 创terms桶聚合
aggs := elastic.NewTermsAggregation().Field("shop_id")
// 创建Sum指标聚合
sumAggs := elastic.NewSumAggregation().Field("price")
// terms聚合嵌套指标聚合
aggs.SubAggregation("total_price", sumAggs)
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值