ES学习demo大全

2 篇文章 0 订阅

为了便于以后使用ES方便,自己整理了ES使用的demo,如下:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"time"

	"github.com/olivere/elastic/v7"
)

// 索引mapping定义,这里仿微博消息结构定义
const mapping = `
{
  "mappings": {
    "properties": {
      "user": {
        "type": "keyword"
      },
      "message": {
        "type": "text"
      },
      "image": {
        "type": "keyword"
      },
      "created": {
        "type": "date"
      },
      "tags": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      },
      "suggest_field": {
        "type": "completion"
      }
    }
  }
}`

type Weibo struct {
	User     string                `json:"user"`               // 用户
	Message  string                `json:"message"`            // 微博内容
	Retweets int                   `json:"retweets"`           // 转发数
	Image    string                `json:"image,omitempty"`    // 图片
	Created  time.Time             `json:"created,omitempty"`  // 创建时间
	Tags     []string              `json:"tags,omitempty"`     // 标签
	Location string                `json:"location,omitempty"` //位置
	Suggest  *elastic.SuggestField `json:"suggest_field,omitempty"`
}

func main() {
	//BasicOperator()
	//DocumentOperator()
	//SearchOperator()
	MetricsAggregation()
	//BucketAggregation()
	//AggregationAnalize()
}

//ES基本操作,包括index创建,文档添加,文档查找,文档删除,文档修改
func BasicOperator() {
	//创建client参数详解
	/*
		client, err := elastic.NewClient(
			// elasticsearch 服务地址,多个服务地址使用逗号分隔
			elastic.SetURL("http://10.0.1.1:9200", "http://10.0.1.2:9200"),
			// 基于http base auth验证机制的账号和密码
			elastic.SetBasicAuth("user", "secret"),
			// 启用gzip压缩
			elastic.SetGzip(true),
			// 设置监控检查时间间隔
			elastic.SetHealthcheckInterval(10*time.Second),
			// 设置请求失败最大重试次数
			elastic.SetMaxRetries(5),
			// 设置错误日志输出
			elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)),
			// 设置info日志输出
			elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))
		if err != nil {
			// Handle error
			panic(err)
		}
		_ = client
	*/

	// 创建client
	client, err := elastic.NewClient(
		elastic.SetURL("http://127.0.0.1:9200", "http://127.0.0.1:9201"),
		elastic.SetBasicAuth("user", "secret"))
	if err != nil {
		// Handle error
		fmt.Printf("连接失败: %v\n", err)
	} else {
		fmt.Println("连接成功")
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 首先检测下weibo索引是否存在
	exists, err := client.IndexExists("weibo").Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
	if !exists {
		// weibo索引不存在,则创建一个
		_, err := client.CreateIndex("weibo").BodyString(mapping).Do(ctx)
		if err != nil {
			// Handle error
			panic(err)
		}
	}

	// 创建创建一条微博
	msg1 := Weibo{User: "olivere", Message: "打酱油的一天", Retweets: 0}

	// 使用client创建一个新的文档
	put1, err := client.Index().
		Index("weibo"). // 设置索引名称
		Id("1").        // 设置文档id
		BodyJson(msg1). // 指定前面声明的微博内容
		Do(ctx)         // 执行请求,需要传入一个上下文对象
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)

	// 根据id查询文档
	get1, err := client.Get().
		Index("weibo"). // 指定索引名
		Id("1").        // 设置文档id
		Do(ctx)         // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}
	if get1.Found {
		fmt.Printf("文档id=%s 版本号=%d 索引名=%s\n", get1.Id, get1.Version, get1.Index)
	}

	// 手动将文档内容转换成go struct对象
	msg2 := Weibo{}
	// 提取文档内容,原始类型是json数据
	data, _ := get1.Source.MarshalJSON()
	// 将json转成struct结果
	json.Unmarshal(data, &msg2)
	// 打印结果
	fmt.Println(msg2.Message)

	//更新数据
	updateser, err := client.Update().
		Index("weibo").                             // 设置索引名
		Id("1").                                    // 文档id
		Doc(map[string]interface{}{"retweets": 0}). // 更新retweets=0,支持传入键值结构
		Do(ctx)                                     // 执行ES查询
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Println(updateser.Id)

	// 根据id删除一条数据
	delser, err := client.Delete().
		Index("weibo").
		Id("1").
		Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Println(delser.Id)
}

// 定义一个文章索引结构,用来存储文章内容
type Article struct {
	Title   string    // 文章标题
	Content string    // 文章内容
	Author  string    // 作者
	Created time.Time // 发布时间
}

//ES文档操作
func DocumentOperator() {
	//1.*****增加文档*****
	// 创建client连接ES
	client, err := elastic.NewClient(
		// elasticsearch 服务地址,多个服务地址使用逗号分隔
		elastic.SetURL("http://127.0.0.1:9200", "http://127.0.0.1:9201"),
		// 基于http base auth验证机制的账号和密码
		elastic.SetBasicAuth("user", "secret"),
		// 启用gzip压缩
		elastic.SetGzip(true),
		// 设置监控检查时间间隔
		elastic.SetHealthcheckInterval(10*time.Second),
		// 设置请求失败最大重试次数
		elastic.SetMaxRetries(5),
		// 设置错误日志输出
		elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)),
		// 设置info日志输出
		elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))

	if err != nil {
		// Handle error
		fmt.Printf("连接失败: %v\n", err)
	} else {
		fmt.Println("连接成功")
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 定义一篇博客
	blog := Article{Title: "golang es教程", Content: "go如何操作ES", Author: "tizi", Created: time.Now()}

	// 使用client创建一个新的文档
	put1, err := client.Index().
		Index("blogs"). // 设置索引名称
		Id("1").        // 设置文档id
		BodyJson(blog). // 指定前面声明struct对象
		Do(ctx)         // 执行请求,需要传入一个上下文对象
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)

	//2.*****查询文档*****
	// 根据id查询文档
	get1, err := client.Get().
		Index("blogs"). // 指定索引名
		Id("1").        // 设置文档id
		Do(ctx)         // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}
	if get1.Found {
		fmt.Printf("文档id=%s 版本号=%d 索引名=%s\n", get1.Id, get1.Version, get1.Index)
	}

	//手动将文档内容转换成go struct对象
	msg2 := Article{}
	// 提取文档内容,原始类型是json数据
	data, _ := get1.Source.MarshalJSON()
	// 将json转成struct结果
	json.Unmarshal(data, &msg2)
	// 打印结果
	fmt.Println(msg2.Title)

	//3.*****批量查询文档*****
	// 查询id等于1,2,3的博客内容
	result, err := client.MultiGet().
		Add(elastic.NewMultiGetItem(). // 通过NewMultiGetItem配置查询条件
						Index("blogs"). // 设置索引名
						Id("1")).       // 设置文档id
		Add(elastic.NewMultiGetItem().Index("blogs").Id("2")).
		Add(elastic.NewMultiGetItem().Index("blogs").Id("3")).
		Do(ctx) // 执行请求

	if err != nil {
		panic(err)
	}

	// 遍历文档
	for _, doc := range result.Docs {
		// 转换成struct对象
		var content Article
		tmp, _ := doc.Source.MarshalJSON()
		err := json.Unmarshal(tmp, &content)
		if err != nil {
			panic(err)
		}

		fmt.Println(content.Title)
	}

	//4.*****更新文档*****
	//4.1***根据id更新文档***
	updateser, err := client.Update().
		Index("blogs").                                 // 设置索引名
		Id("1").                                        // 文档id
		Doc(map[string]interface{}{"Title": "新的文章标题"}). // 更新Title="新的文章标题",支持传入键值结构
		Do(ctx)                                         // 执行ES查询
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Println(updateser.Id)
	//4.2***根据条件,批量更新文档***
	_, err = client.UpdateByQuery("blogs").
		// 设置查询条件,这里设置Author=tizi
		Query(elastic.NewTermQuery("Author", "tizi")).
		// 通过脚本更新内容,将Title字段改为1111111
		Script(elastic.NewScript("ctx._source['Title']='1111111'")).
		// 如果文档版本冲突继续执行
		ProceedOnVersionConflict().
		Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
	//5.*****删除文档*****
	//5.1***根据id删除文档***
	delser, err := client.Delete().
		Index("blogs").
		Id("1"). // 文档id
		Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Println(delser.Id)
	//5.2***根据条件删除文档***
	_, _ = client.DeleteByQuery("blogs"). // 设置索引名
		// 设置查询条件为: Author = tizi
		Query(elastic.NewTermQuery("Author", "tizi")).
		// 文档冲突也继续删除
		ProceedOnVersionConflict().
		Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
}

//ES查询操作,文档操作中使用的是get查询
func SearchOperator() {
	// 创建Client, 连接ES
	client, err := elastic.NewClient(
		// elasticsearch 服务地址,多个服务地址使用逗号分隔
		elastic.SetURL("http://127.0.0.1:9200", "http://127.0.0.1:9201"),
		// 基于http base auth验证机制的账号和密码
		elastic.SetBasicAuth("user", "secret"),
		// 启用gzip压缩
		elastic.SetGzip(true),
		// 设置监控检查时间间隔
		elastic.SetHealthcheckInterval(10*time.Second),
		// 设置请求失败最大重试次数
		elastic.SetMaxRetries(5),
		// 设置错误日志输出
		elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)),
		// 设置info日志输出
		elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))

	if err != nil {
		// Handle error
		fmt.Printf("连接失败: %v\n", err)
	} else {
		fmt.Println("连接成功")
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()
	/*
		//创建数据,以供查找
		for i := 10; i < 20; i++ {
			title := strconv.Itoa(i) + "golang es教程"
			// 定义一篇博客
			blog := Article{Title: title, Content: "go如何操作ES", Author: "tizi365", Created: time.Now()}
			// 使用client创建一个新的文档
			put1, err := client.Index().
				Index("blogs").      // 设置索引名称
				Id(strconv.Itoa(i)). // 设置文档id
				BodyJson(blog).      // 指定前面声明struct对象
				Do(ctx)              // 执行请求,需要传入一个上下文对象
			if err != nil {
				// Handle error
				panic(err)
			}
			fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)
		}
	*/
	//1.*****term查询*****
	// 创建term查询条件,用于精确查询
	termQuery := elastic.NewTermQuery("Author", "tizi365")

	searchResult, err := client.Search().
		Index("blogs").        // 设置索引名
		Query(termQuery).      // 设置查询条件
		Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Pretty(true).          // 查询结果返回可读性较好的JSON格式
		Do(ctx)                // 执行请求

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

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

	if searchResult.TotalHits() > 0 {
		// 查询结果不为空,则遍历结果
		var b1 Article
		// 通过Each方法,将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}

	//2.*****通过terms实现SQL的in查询*****
	// 创建terms查询条件
	termsQuery := elastic.NewTermsQuery("Author", "tizi365", "tizi")

	searchResults, err := client.Search().
		Index("blogs").        // 设置索引名
		Query(termsQuery).     // 设置查询条件
		Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Pretty(true).          // 查询结果返回可读性较好的JSON格式
		Do(ctx)                // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResults.TookInMillis, searchResults.TotalHits())

	if searchResults.TotalHits() > 0 {
		// 查询结果不为空,则遍历结果
		var b1 Article
		// 通过Each方法,将es结果的json结构转换成struct对象
		for _, item := range searchResults.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}

	//3.*****匹配单个字段*****
	// 创建match查询条件
	matchQuery := elastic.NewMatchQuery("Title", "golang es教程")

	searchResult, err = client.Search().
		Index("blogs").        // 设置索引名
		Query(matchQuery).     // 设置查询条件
		Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Do(ctx)                // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

	if searchResult.TotalHits() > 0 {
		// 查询结果不为空,则遍历结果
		var b1 Article
		// 通过Each方法,将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}

	//*****范围查询*****
	// 例1 等价表达式: Created > "2020-07-20" and Created < "2020-07-29"
	/*
		rangeQuery := elastic.NewRangeQuery("Created").
			Gt("2020-07-20").
			Lt("2020-07-29")
	*/
	// 例2 等价表达式: id >= 1 and id < 10
	rangeQuery := elastic.NewRangeQuery("id").
		Gte(8).
		Lte(9)

	searchResult, err = client.Search().
		Index("blogs").        // 设置索引名
		Query(rangeQuery).     // 设置查询条件
		Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Do(ctx)                // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

	if searchResult.TotalHits() > 0 {
		// 查询结果不为空,则遍历结果
		var b1 Article
		// 通过Each方法,将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}

	//*****5.bool组合查询*****
	//bool组合查询,实际上就是组合了前面的查询条件,然后通过类似SQL语句的and和or将查询条件组合起来
	//***5.1MUST查询***
	//类似SQL的and,代表必须匹配的条件
	// 创建bool查询
	boolQuery := elastic.NewBoolQuery().Must()

	// 创建term查询
	termQuery = elastic.NewTermQuery("Author", "tizi")
	matchQuery = elastic.NewMatchQuery("Title", "golang es教程")

	// 设置bool查询的must条件, 组合了两个子查询
	// 表示搜索匹配Author=tizi且Title匹配"golang es教程"的文档
	boolQuery.Must(termQuery, matchQuery)

	searchResult, err = client.Search().
		Index("blogs").        // 设置索引名
		Query(boolQuery).      // 设置查询条件
		Sort("Created", true). // 设置排序字段,根据Created字段升序排序,第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量,从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Do(ctx)                // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

	if searchResult.TotalHits() > 0 {
		// 查询结果不为空,则遍历结果
		var b1 Article
		// 通过Each方法,将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}
	//***5.2must_not查询***
	//跟must的作用相反,用法和must类似
	// 创建bool查询
	boolQuery = elastic.NewBoolQuery().Must()

	// 创建term查询
	termQuery = elastic.NewTermQuery("Author", "tizi")

	// 设置bool查询的must not条件
	boolQuery.MustNot(termQuery)

	//***5.3should条件***
	//类似SQL中的 or, 只要匹配其中一个条件即可
	// 创建bool查询
	boolQuery = elastic.NewBoolQuery().Must()

	// 创建term查询
	termQuery = elastic.NewTermQuery("Author", "tizi")
	matchQuery = elastic.NewMatchQuery("Title", "golang es教程")

	// 设置bool查询的should条件, 组合了两个子查询
	// 表示搜索Author=tizi或者Title匹配"golang es教程"的文档
	boolQuery.Should(termQuery, matchQuery)
}

//聚合分析:综合例子
func AggregationAnalize() {
	// 创建ES client
	client, err := elastic.NewClient()
	if err != nil {
		// Handle error
		panic(err)
	}

	// 创建一个terms聚合,根据user字段分组,同时设置桶排序条件为按计数倒序排序,并且返回前10条桶数据
	timeline := elastic.NewTermsAggregation().Field("type").Size(10).OrderByCountDesc()
	// 创建Date histogram聚合,根据created时间字段分组,按年分组
	histogram := elastic.NewDateHistogramAggregation().Field("created").CalendarInterval("year")

	// 设置timeline的嵌套聚合条件,整体意思就是:首先按user字段分组,然后分组数据内,再次根据created时间字段按年分组,进行了两次分组。
	timeline = timeline.SubAggregation("history", histogram)

	// 执行ES查询
	searchResult, err := client.Search().
		Index("shops").                    // 设置索引名
		Query(elastic.NewMatchAllQuery()). // 设置查询条件
		Aggregation("timeline", timeline). // 设置聚合条件,并为聚合条件设置一个名字
		Pretty(true).                      // 返回可读的json格式
		Do(context.Background())           // 执行
	if err != nil {
		// Handle error
		panic(err)
	}

	// 遍历ES查询结果,因为我们首先使用的是terms聚合条件,
	// 所以查询结果先使用Terms函数和聚合条件的名字读取结果。
	agg, found := searchResult.Aggregations.Terms("timeline")
	if !found {
		// 没有查询到terms聚合结果
		log.Fatalf("we should have a terms aggregation called %q", "timeline")
	}

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

		// 查询嵌套聚合查询的数据
		// 因为我们使用的是Date histogram聚合,所以需要使用DateHistogram函数和聚合名字获取结果
		histogram, found := userBucket.DateHistogram("history")
		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)
			}
		}
	}
}

//聚合分析:指标聚合metrics
//对指标进行统计计算
func MetricsAggregation() {
	// 创建ES client
	client, err := elastic.NewClient()
	if err != nil {
		// Handle error
		panic(err)
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 创建Value Count指标聚合
	//值聚合,主要用于统计文档总数,类似SQL的count函数。
	aggs := elastic.NewValueCountAggregation().
		Field("Created") // 设置统计字段

	searchResult, err := client.Search().
		Index("blogs").                    // 设置索引名
		Query(elastic.NewMatchAllQuery()). // 设置查询条件
		Aggregation("total", aggs).        // 设置聚合条件,并为聚合条件设置一个名字, 支持添加多个聚合条件,命名不一样即可。
		Size(0).                           // 设置分页参数 - 每页大小,设置为0代表不返回搜索结果,仅返回聚合分析结果
		Do(ctx)                            // 执行请求

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

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

	//Cardinality基数聚合
	//基数聚合,也是用于统计文档的总数,跟Value Count的区别是,基数聚合会去重,不会统计重复的值,类似SQL的count(DISTINCT 字段)用法
	// 创建Cardinality指标聚合
	aggss := elastic.NewCardinalityAggregation().
		Field("Created") // 设置统计字段

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

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

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

	//Avg聚合:求平均值
	// 创建Avg指标聚合
	aggs_avg := elastic.NewAvgAggregation().
		Field("Created") // 设置统计字段

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

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

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

	//Sum聚合:求和计算
	// 创建Sum指标聚合
	aggs_sum := elastic.NewSumAggregation().
		Field("Created") // 设置统计字段

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

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

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

	//Max聚合:求最大值计算
	// 创建Sum指标聚合
	aggs_max := elastic.NewMaxAggregation().
		Field("Created") // 设置统计字段

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

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

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

	//Min聚合:求最小值计算
	// 创建Sum指标聚合
	aggs_min := elastic.NewMinAggregation().
		Field("Created") // 设置统计字段

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

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

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

//聚合分析:桶聚合bucket
//Elasticsearch桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计。
func BucketAggregation() {
	//CreateBucketAggregationData()
	// 创建ES client
	client, err := elastic.NewClient()
	if err != nil {
		// Handle error
		panic(err)
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 1.*****创建Terms桶聚合*****
	aggs := elastic.NewTermsAggregation().
		Field("type") // 根据shop_id字段值,对数据进行分组

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

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

	// 使用Terms函数和前面定义的聚合条件名称,查询结果
	agg, found := searchResult.Aggregations.Terms("shop")
	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)
	}

	//2.*****Histogram聚合*****
	// 创建Histogram桶聚合
	aggs_his := elastic.NewHistogramAggregation().
		Field("price"). // 根据price字段值,对数据进行分组
		Interval(100)   //  分桶的间隔为50,意思就是price字段值按50间隔分组

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

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

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

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

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

	//3.*****Date histogram聚合*****
	// 创DateHistogram桶聚合
	aggs_datahis := elastic.NewDateHistogramAggregation().
		Field("created"). // 根据date字段值,对数据进行分组
		//  分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
		CalendarInterval("month").
		// 设置返回结果中桶key的时间格式
		Format("yyyy-MM-dd")

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

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

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

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

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

	//4.*****Range聚合*****
	// 创Range桶聚合
	aggs_ran := elastic.NewRangeAggregation().
		Field("price").         // 根据price字段分桶
		AddUnboundedFrom(100).  // 范围配置, 0 - 100
		AddRange(100.0, 200.0). // 范围配置, 100 - 200
		AddUnboundedTo(200.0)   // 范围配置,> 200的值

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

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

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

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

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

	//5.*****嵌套*****
	// 创terms桶聚合
	aggs_qt := elastic.NewTermsAggregation().Field("type")
	// 创建Sum指标聚合
	sumAggs_qt := elastic.NewSumAggregation().Field("price")
	// terms聚合嵌套指标聚合
	timeline := aggs_qt.SubAggregation("total_price", sumAggs_qt)

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

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

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

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

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

type Product struct {
	Name    string    `json:"name"`    // 产品名称
	Type    string    `json:"type"`    // 产品类型
	Price   int       `json:"price"`   // 产品价格
	Created time.Time `json:"created"` // 生产时间
}

const mappings = `
{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "type": {
        "type": "keyword"
      },
      "created": {
        "type": "date"
      },
      "price": {
        "type": "integer"
      }
    }
  }
}`

func CreateBucketAggregationData() {
	// 创建client
	client, err := elastic.NewClient(
		elastic.SetURL("http://127.0.0.1:9200", "http://127.0.0.1:9201"),
		elastic.SetBasicAuth("user", "secret"))
	if err != nil {
		// Handle error
		fmt.Printf("连接失败: %v\n", err)
	} else {
		fmt.Println("连接成功")
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 首先检测下weibo索引是否存在
	exists, err := client.IndexExists("shops").Do(ctx)
	if err != nil {
		// Handle error
		panic(err)
	}
	if !exists {
		// weibo索引不存在,则创建一个
		_, err := client.CreateIndex("shops").BodyString(mappings).Do(ctx)
		if err != nil {
			// Handle error
			panic(err)
		}
	}

	// work
	msg1 := Product{Name: "keyboad", Price: 250, Created: time.Now(), Type: "work"}

	// 使用client创建一个新的文档
	put1, err := client.Index().
		Index("shops"). // 设置索引名称
		Id("5").        // 设置文档id
		BodyJson(msg1). // 指定前面声明的微博内容
		Do(ctx)         // 执行请求,需要传入一个上下文对象
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)
}

//总结:
//1.使用transname进行桶分组
//2.使用耗时、错误码等进行聚合
//3.根据聚合结果进行数据结果的整合,并将结果输出

备注:可以在梯子网进行学习https://www.tizi365.com/archives/850.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的 Spring Boot 集成 Elasticsearch 的示例: 1. 首先,需要在 pom.xml 文件中添加 Elasticsearch 的依赖: ```xml <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.10.2</version> </dependency> ``` 2. 然后,在 application.yml 或 application.properties 中配置 Elasticsearch 的地址和端口: ```yaml spring: data: elasticsearch: cluster-name: elasticsearch cluster-nodes: localhost:9200 ``` 3. 创建一个实体类,用于映射 Elasticsearch 中的数据: ```java @Data @NoArgsConstructor @AllArgsConstructor @Builder @Document(indexName = "user", shards = 1, replicas = 0) public class User { @Id private String id; private String name; private Integer age; } ``` 4. 创建一个 Elasticsearch 的操作类,用于增删改查: ```java @Component public class ElasticsearchOperations { private final ElasticsearchRestTemplate elasticsearchRestTemplate; public ElasticsearchOperations(ElasticsearchRestTemplate elasticsearchRestTemplate) { this.elasticsearchRestTemplate = elasticsearchRestTemplate; } public void save(User user) { IndexQuery indexQuery = new IndexQueryBuilder() .withIndexName("user") .withObject(user) .build(); elasticsearchRestTemplate.index(indexQuery); } public void delete(String id) { elasticsearchRestTemplate.delete("user", id); } public void update(User user) { IndexRequest indexRequest = new IndexRequest("user") .id(user.getId()) .source(new ObjectMapper().convertValue(user, Map.class)); UpdateRequest updateRequest = new UpdateRequest("user", user.getId()) .doc(new ObjectMapper().convertValue(user, Map.class)) .upsert(indexRequest); elasticsearchRestTemplate.update(updateRequest); } public List<User> search(String keyword) { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("name", keyword)) .build(); return elasticsearchRestTemplate.queryForList(searchQuery, User.class); } } ``` 5. 最后,在 Controller 中使用 ElasticsearchOperations 进行增删改查操作: ```java @RestController @RequestMapping("/users") public class UserController { @Autowired private ElasticsearchOperations elasticsearchOperations; @PostMapping public void save(@RequestBody User user) { elasticsearchOperations.save(user); } @DeleteMapping("/{id}") public void delete(@PathVariable String id) { elasticsearchOperations.delete(id); } @PutMapping public void update(@RequestBody User user) { elasticsearchOperations.update(user); } @GetMapping public List<User> search(@RequestParam String keyword) { return elasticsearchOperations.search(keyword); } } ``` 以上就是一个简单的 Spring Boot 集成 Elasticsearch 的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XiZhi_BUAA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值