golang操作ES

1,670 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

golang操作ES

本文主要是简单介绍 golang调用ES的增删改查方法,具体文档详见:github.com/olivere/ela…

连接ES

esClient, err = elastic.NewClient(elastic.SetURL(host_address), elastic.SetSniff(false))

创建索引Index

ES的Index就是数据库的表,按天创建索引, 映射(mapping) 映射是定义一个文档以及其所包含的字段如何被存储和索引的方法。

#定义index的索引接口
var mapping = `{
	"settings":{
		"number_of_shards":1,
		"number_of_replicas":0
	},
	"properties":{
		"@timestamp":{
			"format":"strict_date_optional_time||epoch_millis",
			"type":"date",
			"enabled":true
		}
	}
}`

var DATESET sync.Map

具体参考ES Mapping详解

func createIndex(index string) string {
	t := time.Now()
	date := t.Format("20060102")
	findex := index + date
	_, ok := DATESET.Load(findex)
	if !ok {
		exists, err := esClient.IndexExists(findex).Do(context.Background())
		if err != nil {
			panic(err)
		}
		if !exists {
			esClient.CreateIndex(findex).BodyString(mapping).Do(context.Background())
		}
		DATESET.Store(findex, date)
	}
	return findex
}

删除索引

func deleteIndex(indexName string) error {
	var err error
	ctx := context.Background()
	exists, err := esClient.IndexExists(indexName).Do(ctx)
	if err != nil {
		log.Println("IndexExists" + err.Error())
		return err
	}
	if exists {
		deleteIndex, err := esClient.DeleteIndex(indexName).Do(ctx)
		fmt.Println("DeleteIndex[", indexName, "]=>", err, "res=", deleteIndex)
		if err != nil {
			// Handle error
			return err
		}
		if !deleteIndex.Acknowledged {
			// Not acknowledged
			return errors.New("delete index is not Acknowledged")
		}
	}
	return err
}

写入数据

tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
tweet3 := tweet{User: "sandrae", Message: "Cycling is fun."}

// Add all documents 需要制定IndexName,和ID,删除数据的时候可以根据ID单条删除数据
_, err := client.Index().Index(IndexName).Id("1").BodyJson(&tweet1).Do(context.TODO())
if err != nil {
  t.Fatal(err)
}

_, err = client.Refresh().Index(IndexName).Do(context.TODO())
if err != nil {
  t.Fatal(err)
}

// Count documents 统计Index下的数据量
count, err := client.Count(IndexName).Do(context.TODO())
if err != nil {
  t.Fatal(err)
}

查询数据

  1. 根据ID查询
// Get document 1 根据INDEX和ID查询
res, err := client.Get().Index(IndexName).Id("1").Do(context.TODO())
if err != nil {
  t.Fatal(err)
}
if res.Found != true {
  t.Errorf("expected Found = true; got %v", res.Found)
}
if res.Source == nil {
  t.Errorf("expected Source != nil; got %v", res.Source)
}
  1. 根据字段查询
#mapping 定义
testMapping = `
{
	"settings":{
		"number_of_shards":1,
		"number_of_replicas":0
	},
	"mappings":{
		"properties":{
			"user":{
				"type":"keyword"
			},
			"message":{
				"type":"text",
				"store": true,
				"fielddata": true
			},
			"tags":{
				"type":"keyword"
			},
			"location":{
				"type":"geo_point"
			},
			"suggest_field":{
				"type":"completion"
			}
		}
	}
}
`
#创建索引
createIndex, err := client.CreateIndex(testIndexName).Body(testMapping).Do(context.TODO())
if err != nil {
  t.Fatal(err)
}
if createIndex == nil {
  t.Errorf("expected result to be != nil; got: %v", createIndex)
}
# 准备数据
tweet1 := tweet{
		User:     "olivere",
		Retweets: 108,
		Message:  "Welcome to Golang and Elasticsearch.",
		Image:    "http://golang.org/doc/gopher/gophercolor.png",
		Tags:     []string{"golang", "elasticsearch"},
		Location: "48.1333,11.5667", // lat,lon
		Created:  time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
	}
	tweet2 := tweet{
		User:     "olivere",
		Retweets: 0,
		Message:  "Another unrelated topic.",
		Tags:     []string{"golang"},
		Location: "48.1189,11.4289", // lat,lon
		Created:  time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
	}
	tweet3 := tweet{
		User:     "sandrae",
		Retweets: 12,
		Message:  "Cycling is fun.",
		Tags:     []string{"sports", "cycling"},
		Location: "47.7167,11.7167", // lat,lon
		Created:  time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
	}
# 插入数据
	_, err := client.Index().Index(testIndexName).Id("1").BodyJson(&tweet1).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Id("2").BodyJson(&tweet2).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Id("3").BodyJson(&tweet3).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}
# 查询全量数据
all := NewMatchAllQuery()
searchResult, err := client.Search().
		Index(testIndexName).
		Query(all).
		Size(100).               //limit返回结果集
                Sort("created", false).  //按时间排序
		Pretty(true).
		Do(context.TODO())
# 根据条件查询
{
    "query": {
        "match": {"message": "吃饭睡觉"} //模糊查询 匹配字段message中跟”吃饭睡觉“相关的所有数据,比如”吃饭xxxx“、”睡觉xxxxx“、”吃xxxx“........;
    }
}
{
    "query": {
        "match_phrase": {"message": "吃饭睡觉"} //精确查询 确匹配出message等于”吃饭睡觉“的所有数据
    }
}
{
    "query": {
        "multi_match": {
            "query": "小陈",
            "fields": ["user", "message"]  //多字段模糊查询
        }
    }
}
searchResult, err := client.Search().
		Index(testIndexName).
		Source(`{"query":{"match_all":{}}}`). // sets the JSON request
		Do(context.TODO())
# 查询特定字段
searchResult, err := client.Search().
		Index(testIndexName).
		Source(`{"query":{"match_all":{}}}`). // sets the JSON request
		StoredFields("message").
		DocvalueFields("retweets").
		Sort("created", true).
		Do(context.TODO())
#结果集合在searchResult.Hits.Hits.Fileds中

ES的查询博大精深,本篇文章属于基础入门,内容来源于官网

参考资料

  1. ES从入门到实战
  2. ES简单实用DSL查询
  3. ES搜索和DSL
  4. github.com/olivere/ela…