导包
require (
github.com/elastic/go-elasticsearch/v7 v7.12.0
)
连接客户端
var (
client *es.Client
)
func init() {
var err error
client, err = es.NewClient(es.Config{
Addresses: []string{"http://192.168.6.39:9201"},
Transport: &http.Transport{
MaxIdleConnsPerHost: 10,
ResponseHeaderTimeout: time.Second,
DialContext: (&net.Dialer{Timeout: time.Second}).DialContext,
TLSClientConfig: &tls.Config{
MaxVersion: tls.VersionTLS11,
InsecureSkipVerify: true,
},
},
})
if err != nil {
log.Fatal(err)
}
}
索引操作 CRUD
添加索引
func TestAddIndex(t *testing.T) {
response, _ := client.API.Indices.Create("es_test")
fmt.Printf("response: %v\n", response)
}
查询索引
func TestGetIndex(t *testing.T) {
response, _ := client.API.Indices.Get([]string{"es_test"})
fmt.Printf("response: %v\n", response)
}
删除索引
func TestDelIndex(t *testing.T) {
response, _ := client.API.Indices.Delete([]string{"es_test_book"})
fmt.Printf("response: %v\n", response)
}
文档操作
创建索引
type Book struct {
ID string `json:"id"`
Author string `json:"author"`
Name string `json:"name"`
Pages int `json:"pages"`
Price float64 `json:"price"`
PubDate *time.Time `json:"pubDate"`
Summary string `json:"summary"`
}
func TestAddDoc(t *testing.T) {
assertions := assert.New(t)
body := &bytes.Buffer{}
pubDate := time.Now()
err := json.NewEncoder(body).Encode(&Book{
Author: "金庸",
Price: 96.0,
Name: "天龙八部",
Pages: 1978,
PubDate: &pubDate,
Summary: "...",
})
assertions.Nil(err)
response, err := client.Create("es_test_book", "1", body)
assertions.Nil(err)
t.Log(response)
}
覆盖性更新文档
func TestIndexDocument(t *testing.T) {
a := assert.New(t)
body := &bytes.Buffer{}
pubDate := time.Now()
err := json.NewEncoder(body).Encode(&Book{
Author: "金庸",
Price: 96.0,
Name: "天龙八部",
Pages: 1978,
PubDate: &pubDate,
Summary: "...",
})
a.Nil(err)
response, err := client.Index("es_book", body, client.Index.WithDocumentID("1"))
a.Nil(err)
t.Log(response)
}
局部性更新文档,
type doc struct {
Doc interface{} `json:"doc"`
}
type Book1 struct {
Author string `json:"author,omitempty"`
Name string `json:"name,omitempty"`
Pages int `json:"pages,omitempty"`
Price float64 `json:"price,omitempty"`
PubDate *time.Time `json:"pubDate,omitempty"`
Summary string `json:"summary,omitempty"`
}
func TestPartialUpdateDocument(t *testing.T) {
a := assert.New(t)
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(&doc{
Doc: &Book1{
Name: "《天龙八部》",
},
})
a.Nil(err)
response, err := client.Update("es_book", "1", body)
a.Nil(err)
t.Log(response)
}
删除文档
func TestDeleteDocument(t *testing.T) {
a := assert.New(t)
response, err := client.Delete("es_book", "1")
a.Nil(err)
t.Log(response)
}
获取文档
func TestGetDocument(t *testing.T) {
assertions := assert.New(t)
response, err := client.Get("es_book", "1")
assertions.Nil(err)
t.Log(response)
}
文档的批量操作添加跟删除
/ 批量操作对应ES的REST API是:
func TestBulk(t *testing.T) {
createBooks := []*Book{
{
ID: "10002",
Name: "神雕侠侣",
Author: "金庸",
},
{
ID: "10003",
Name: "射雕英雄传",
Author: "金庸",
},
}
deleteBookIds := []string{"1"}
a := assert.New(t)
body := &bytes.Buffer{}
for _, book := range createBooks {
meta := []byte(fmt.Sprintf(`{ "index" : { "_id" : "%s" } }%s`, book.ID, "\n"))
data, err := json.Marshal(book)
a.Nil(err)
data = append(data, "\n"...)
body.Grow(len(meta) + len(data))
body.Write(meta)
body.Write(data)
}
for _, id := range deleteBookIds {
meta := []byte(fmt.Sprintf(`{ "delete" : { "_id" : "%s" } }%s`, id, "\n"))
body.Grow(len(meta))
body.Write(meta)
}
t.Log(body.String())
response, err := client.Bulk(body, client.Bulk.WithIndex("book"))
a.Nil(err)
t.Log(response)
}
文档搜索 单个字段
func TestSearchByOneDoc(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"match": map[string]interface{}{
"name": "神雕侠侣",
},
},
"highlight": map[string]interface{}{
"pre_tags": []string{""},
"post_tags": []string{""},
"fields": map[string]interface{}{
"title": map[string]interface{}{},
},
},
}
marshal, _ := json.Marshal(query)
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
查询操作
提高某个字段权重,可以使用 ^ 字符语法为单个字段提升权重,在字段名称的末尾添加 ^boost ,其中 boost 是一个浮点数:
func TestSearchBy(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"multi_match": map[string]interface{}{
"query": "《天龙八部》",
"fields": []string{"name", "author^2"},
},
},
"highlight": map[string]interface{}{
"pre_tags": []string{""},
"post_tags": []string{""},
"fields": map[string]interface{}{
"title": map[string]interface{}{},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
// 显示所有的
func TestSearchByAll(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"match_all": map[string]interface{}{},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
// 范围查询通过range实现范围查询,类似SQL语句中的>, >=, <, <=表达式。 gte范围参数 - 等价于>= lte范围参数 - 等价于 <= 范围参数可以只写一个,例如:仅保留 “gte”: 10, 则代表 FIELD字段 >= 10
func TestSearchByRang(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"range": map[string]interface{}{
"price": map[string]interface{}{
"gte": "0",
"lte": "20",
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
文档搜索 多个字段
func TestSearchByInesDoc(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"multi_match": map[string]interface{}{
"query": "金",
"fields": []string{"name", "author"},
},
},
"highlight": map[string]interface{}{
"pre_tags": []string{""},
"post_tags": []string{""},
"fields": map[string]interface{}{
"title": map[string]interface{}{},
},
},
}
marshal, _ := json.Marshal(query)
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
布尔 must and
func TestSearchByAnd(t *testing.T) {
a := assert.New(t)
name := "金庸"
price := "0"
query := map[string]interface{}{
"query": map[string]interface{}{
"bool": map[string]interface{}{
"must": []map[string]interface{}{
{
"match": map[string]interface{}{
"author": name,
},
},
{
"match": map[string]interface{}{
"price": price,
},
},
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
布尔查询 or
func TestSearchByOr(t *testing.T) {
a := assert.New(t)
name := "金庸"
price := "0"
query := map[string]interface{}{
"query": map[string]interface{}{
"bool": map[string]interface{}{
"should": []map[string]interface{}{
{
"match": map[string]interface{}{
"author": name,
},
},
{
"match": map[string]interface{}{
"price": price,
},
},
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
精确度查询
func TestSearchByTerm(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"query": map[string]interface{}{
"term": map[string]interface{}{
"name.keyword": "射雕英雄传",
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
使用Mysql 的方式查询
func TestSearchBySql(t *testing.T) {
a := assert.New(t)
index := "book"
query := map[string]interface{}{
"query": "select count(1) from " + index,
}
jsonBody, _ := json.Marshal(query)
t.Log(string(jsonBody))
response, err := client.SQL.Query(bytes.NewReader(jsonBody), client.SQL.Query.WithContext(context.Background()))
a.Nil(err)
t.Log(response)
}
Cat 的操作
func TestCatDemo(t *testing.T) {
health, _ := client.Cat.Health()
t.Log(health.String())
allocation, _ := client.Cat.Allocation(client.Cat.Allocation.WithNodeID(""))
t.Log(allocation)
shards, _ := client.Cat.Shards()
t.Log(shards)
master, _ := client.Cat.Master()
t.Log(master)
nodes, _ := client.Cat.Nodes()
t.Log(nodes)
tasks, _ := client.Cat.Tasks()
t.Log(tasks)
response, _ := client.Cat.Indices(client.Cat.Indices.WithIndex(""))
t.Log(response)
segments, _ := client.Cat.Segments()
t.Log(segments)
count, _ := client.Cat.Count()
t.Log(count)
recovery, _ := client.Cat.Recovery()
t.Log(recovery)
pendingTasks, _ := client.Cat.PendingTasks()
t.Log(pendingTasks)
aliases, _ := client.Cat.Aliases()
t.Log(aliases)
threadPool, _ := client.Cat.ThreadPool()
t.Log(threadPool)
plugins, _ := client.Cat.Plugins()
t.Log(plugins)
fielddata, _ := client.Cat.Fielddata()
t.Log(fielddata)
nodeattrs, _ := client.Cat.Nodeattrs()
t.Log(nodeattrs)
templates, _ := client.Cat.Templates()
t.Log(templates)
}
聚合查询
聚合 group by
func TestAggGroupBy(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"terms": map[string]interface{}{
"field": "name.keyword",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
count
func TestAggCount(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"value_count": map[string]interface{}{
"field": "name.keyword",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Cardinality 基数聚合,也是用于统计文档的总数,跟Value Count的区别是,基数聚合会去重,不会统计重复的值,类似SQL的count(DISTINCT 字段)用法。
func TestAggCardinality(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"cardinality": map[string]interface{}{
"field": "name.keyword",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Avg
func TestAggAvg(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"avg": map[string]interface{}{
"field": "price",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
sum
func TestAggSum(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"sum": map[string]interface{}{
"field": "price",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Max
func TestAggMax(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"max": map[string]interface{}{
"field": "price",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Min
func TestAggMin(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"min": map[string]interface{}{
"field": "price",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
综合
func TestAgg(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"min": map[string]interface{}{
"field": "price",
},
},
"count_name1": map[string]interface{}{
"value_count": map[string]interface{}{
"field": "name.keyword",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
// Terms聚合 terms聚合的作用跟SQL中group by作用一样,都是根据字段唯一值对数据进行分组(分桶),字段值相等的文档都分到同一个桶内。select price, count(*) from book group by price
func TestAggTerms(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"terms": map[string]interface{}{
"field": "price",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Histogram聚合
func TestAggHistogram(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"histogram": map[string]interface{}{
"field": "price",
"interval": 50,
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Date histogram
func TestAggDateHistogram(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"date_histogram": map[string]interface{}{
"field": "pubDate",
"calendar_interval": "month",
"format": "yyyy-MM-dd",
},
},
},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
Range
func TestAggRange(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"range": map[string]interface{}{
"field": "price",
"ranges": []interface{}{
map[string]float64{"to": 100.0},
map[string]float64{"from": 100.0, "to": 200.0},
map[string]float64{"from": 200.0},
},
},
}},
"from": 0,
"size": 1,
"sort": []map[string]interface{}{
{"pubDate": []map[string]interface{}{
{"order": "desc"},
},
},
},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}
综合案例
func TestAggs(t *testing.T) {
a := assert.New(t)
query := map[string]interface{}{
"aggs": map[string]interface{}{
"count_name1": map[string]interface{}{
"range": map[string]interface{}{
"field": "price",
"ranges": []interface{}{
map[string]float64{"to": 100.0},
map[string]float64{"from": 100.0, "to": 200.0},
map[string]float64{"from": 200.0},
},
},
},
"aggs": map[string]interface{}{
"count_name": map[string]interface{}{
"min": map[string]interface{}{
"field": "price",
},
},
}},
}
marshal, _ := json.Marshal(query)
t.Log(string(marshal))
response, err := client.Search(client.Search.WithIndex("book"), client.Search.WithBody(bytes.NewReader(marshal)))
a.Nil(err)
t.Log(response)
}