Go Elasticsearch 更新快速入门

Posted 恋喵大鲤鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go Elasticsearch 更新快速入门相关的知识,希望对你有一定的参考价值。


1.根据 ID 修改

可以根据文档 ID 更新对应的文档。

// Update 修改文档
// param: index 索引; id 文档ID; m 待更新的字段键值结构
func Update(ctx context.Context, index, id string, doc interface) error 
	_, err := GetESClient().Update().Index(index).Id(id).Doc(doc).Refresh("true").Do(ctx)
	return err

注意:修改不存在的文档将报elastic: Error 404 (Not Found)错误。

比如修改文档 ID 为 1 的用户名改为 “jack”。

err := Update(context.Background(), index, "1", map[string]interface"username": "jack")

对应的 RESTful api 为:

POST es_index_userinfo/_update/1?refresh=wait_for

   "doc": 
    "username": "jack"
  

2.根据 ID 修改(不存在则插入)

如果文档不存在,作为新文档插入,则可以使用 upsert。

// Upsert 修改文档(不存在则插入)
// params index 索引; id 文档ID; m 待更新的字段键值结构
func Upsert(ctx context.Context, index, id string, doc interface) error 
	_, err := GetESClient().Update().Index(index).Id(id).Doc(doc).Upsert(doc).Refresh("true").Do(ctx)
	return err

比如修改文档 ID 为 9 的部分信息,如果文档不存在则插入。

ctx := context.Background()
m := map[string]interface
	"id":       9,
	"username": "jerry",
	"age":      11,

err := Upsert(ctx, "es_index_userinfo", "9", m)

对应的 RESTful api 为:

POST es_index_userinfo/_update/9?refresh=true

  "doc":
		"id":       9,
		"username": "jerry",
		"age":      11
	,
	"doc_as_upsert": true

3.根据条件更新

我们也可以根据条件来更新符合条件的文档,即 Update by Query。

// UpdateByQuery 根据条件修改文档
// param: index 索引; query 条件; script 脚本指定待更新的字段与值
func UpdateByQuery(ctx context.Context, index string, query elastic.Query, script *elastic.Script) (int64, error) 
	rsp, err := GetESClient().UpdateByQuery(index).Query(query).Script(script).Refresh("true").Do(ctx)
	if err != nil 
		return 0, err
	
	return rsp.Updated, nil

注意:Refresh 只能指定 true 或 false(缺省值),不能指定 wait_for。

比如我将更新用户名为 alice,年龄小于等于 18 岁的用户昵称和祖籍。

query := elastic.NewBoolQuery()
query.Filter(elastic.NewTermQuery("username", "alice"))
query.Filter(elastic.NewRangeQuery("age").Lte(18))
script := elastic.NewScriptInline("ctx._source.nickname=params.nickname;ctx._source.ancestral=params.ancestral").Params(
	map[string]interface
		"nickname":  "cat",
		"ancestral": "安徽",
	)
ret, err := UpdateByQuery2ES(context.Background(), index, query, script)

对应的 RESTful api 为:

POST /es_index_userinfo/_update_by_query?refresh=true

  "query":
     "bool":
       "filter":[
         "term":"username":"alice",
         "range" : "age" : "lte" : 18
         ]
     
  ,
  "script": 
    "source": "ctx._source['nickname'] = 'cat';ctx._source['ancestral'] ='安徽'"
  

4.批量更新

同样地,借助 BulkService + BulkUpdateRequest 可实现对文档的批量修改。

// UpdateBulk 批量修改文档
func UpdateBulk(ctx context.Context, index string, ids []string, docs []interface) error 
	bulkService := GetESClient().Bulk().Index(index).Refresh("true")
	for i := range ids 
		doc := elastic.NewBulkUpdateRequest().Id(ids[i]).Doc(docs[i])
		bulkService.Add(doc)
	
	res, err := bulkService.Do(ctx)
	if err != nil 
		return err
	
	if len(res.Failed()) > 0 
		return errors.New(res.Failed()[0].Error.Reason)
	
	return nil


// UpsertBulk 批量修改文档(不存在则插入)
func UpsertBulk(ctx context.Context, index string, ids []string, docs []interface) error 
	bulkService := GetESClient().Bulk().Index(index).Refresh("true")
	for i := range ids 
		doc := elastic.NewBulkUpdateRequest().Id(ids[i]).Doc(docs[i]).Upsert(docs[i])
		bulkService.Add(doc)
	
	res, err := bulkService.Do(ctx)
	if err != nil 
		return err
	
	if len(res.Failed()) > 0 
		return errors.New(res.Failed()[0].Error.Reason)
	
	return nil

下面是调用示例:

func main() 
	ctx := context.Background()
	// id 9 和 10 均存在
	ids := []string"9", "10"
	docs := []interface
		map[string]interface
			"username": "tom",
		,
		map[string]interface
			"username": "alice",
		,
	
	// UpdateBulk 全部成功
	err := UpdateBulk(ctx, "es_index_userinfo", ids, docs)
	fmt.Printf("UpdateBulk all success err is %v\\n", err)

	// id 10 存在,id 11 文档不存在
	ids = []string"10", "11"
	docs = []interface
		map[string]interface
			"username": "angela",
		,
		map[string]interface
			"username": "bill",
		,
	
	// UpdateBulk 部分成功
	err = UpdateBulk(ctx, "es_index_userinfo", ids, docs)
	fmt.Printf("UpdateBulk partial success err is %v\\n", err)
	
	ids = []string"10", "11"
	docs = []interface
		map[string]interface
			"id":       10,
			"username": "tony",
		,
		map[string]interface
			"id":       11,
			"username": "pony",
		,
	
	// UpsertBulk 理论上不会部分成功
	err = UpsertBulk(ctx, "es_index_userinfo", ids, docs)
	fmt.Printf("UpsertBulk all success err is %v\\n", err)

分别输出:

UpdateBulk all success err is <nil>
UpdateBulk partial success err is [_doc][11]: document missing
UpsertBulk all success err is <nil>

对应的 RESTful api 为:

// UpdateBulk 全部成功
POST /es_index_userinfo/_bulk
"update":"_id":"9"
"doc":"username":"tom"
"update":"_id":"10"
"doc":"username": "alice"

// UpdateBulk 部分成功
POST /es_index_userinfo/_bulk
"update":"_id":"10"
"doc":"username":"angela"
"update":"_id":"11"
"doc":"username": "bill"

// Upsert 理论上不会部分成功
POST /es_index_userinfo/_bulk
"update":"_id":"10"
"doc":"id":10, "username":"tony", "doc_as_upsert" : true
"update":"_id":"11"
"doc":"id":11, "username": "pony", "doc_as_upsert" : true

参考文献

elastic - pkg.dev
elastic - type UpdateService
elastic - type UpdateByQueryService
elastic - type BulkService
elastic - type BulkUpdateRequest
Elasticsearch Guide [7.15] » REST APIs » Document APIs » Update API
Elasticsearch Guide [7.13] » REST APIs » Document APIs » Update By Query API
Elasticsearch Guide [7.15] » REST APIs » Document APIs » Bulk API

以上是关于Go Elasticsearch 更新快速入门的主要内容,如果未能解决你的问题,请参考以下文章

Go Elasticsearch 删除快速入门

Go Elasticsearch 删除快速入门

Go Elasticsearch CRUD 快速入门

Go Elasticsearch 查询快速入门

Go Elasticsearch 查询快速入门

Go Elasticsearch CRUD 快速入门