How do I use olivere's elastic client.Update() service to change array fields, generic string fields and possibly nested struct fields?

huangapple go评论95阅读模式
英文:

How do I use olivere's elastic client.Update() service to change array fields, generic string fields and possibly nested struct fields?

问题

https://github.com/olivere/elastic
版本 5.x

维基文档对于client.Update()的工作原理并不清楚。它需要完全更改一个字段和修改数组。例如,在维基文档的示例中,如何添加和删除标签到一条推文,或者更改推文的内容?另外,如果一条推文在Go中表示为一个包含名为"echo"的嵌套结构体,该结构体包含一个类型为int的foo,一个类型为string的content和另一个类型为字符串数组的字段,如果可能的话,如何使用client.Update()来更改这些字段中的任何一个?

在我的个人示例中,我有这个函数:

func UpdateEntryContent(eclient *elastic.Client, entryID string, newContent []rune) error{
    ctx:=context.Background()

    exists, err := eclient.IndexExists(ENTRY_INDEX).Do(ctx)
    if err != nil {return err}
    if !exists {return errors.New("Index does not exist")}

    _, err = eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).
        Script("ctx._source.Content = newCont").
        ScriptParams(map[string]interface{}{"newCont": newContent}).
        Do(ctx)

    if err != nil {return err}

    return nil
}

但是,当我尝试编译时,我遇到以下错误:

无法将"type string"的"ctx._source.Content = newCont"作为参数传递给eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).Script

eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).Script("ctx._source.Content = newCont")。ScriptParams未定义(*elastic.UpdateService类型没有ScriptParams字段或方法)

英文:

https://github.com/olivere/elastic
Version 5.x

The wiki documentation isn't really clear on how client.Update() works. It's needed to completely change a field and to modify arrays. i.e. in the example in the wiki documentation, how would one go about appending and removing tags to a tweet or changing a tweet's content? Also if a tweet was represented in go as a struct and I added a nested struct called "echo" which contains a foo of type int, content of type string and another type string array, how would one go about changing any of these fields using client.Update() if it's even possible?

In my personal example I have this function:

func UpdateEntryContent(eclient *elastic.Client, entryID string, newContent []rune) error{
	ctx:=context.Background()

	exists, err := eclient.IndexExists(ENTRY_INDEX).Do(ctx)
	if err != nil {return err}
	if !exists {return errors.New("Index does not exist")}

	_, err = eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).
		Script("ctx._source.Content = newCont").
		ScriptParams(map[string]interface{}{"newCont": newContent}).
		Do(ctx)

	if err != nil {return err}

	return nil
}

But I get this following error when I try to compile:

cannot use "ctx._source.Content = newCont" (type string) as type *elastic.Script in argument to eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).Script

eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).Script("ctx._source.Content = newCont").ScriptParams undefined (type *elastic.UpdateService has no field or method ScriptParams)

答案1

得分: 1

Script方法接受一个*elastic.Script,而不是一个字符串。ScriptParams方法也可以在*elastic.Script上找到,它被称为Params,而不是在*elastic.UpdateService上。

func UpdateEntryContent(eclient *elastic.Client, entryID string, newContent []rune) error{
    ctx := context.Background()

    exists, err := eclient.IndexExists(ENTRY_INDEX).Do(ctx)
    if err != nil {
        return err
    }
    if !exists {
        return errors.New("Index does not exist")
    }

    script := elastic.NewScript("ctx._source.Content = newCont").Params(map[string]interface{}{"newCont": newContent})

    _, err = eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).
        Script(script).
        Do(ctx)

    if err != nil {
        return err
    }

    return nil
}

你可以通过GoDoc或查看源代码来获取有关该包的更多信息。

英文:

The Script method accepts a *elastic.Script, not a string. The ScriptParams method is also found on *elastic.Script as Params instead of being on *elastic.UpdateService.

func UpdateEntryContent(eclient *elastic.Client, entryID string, newContent []rune) error{
    ctx:=context.Background()

    exists, err := eclient.IndexExists(ENTRY_INDEX).Do(ctx)
    if err != nil {return err}
    if !exists {return errors.New("Index does not exist")}

    script := elastic.NewScript("ctx._source.Content = newCont").Params(map[string]interface{}{"newCont": newContent})

    _, err = eclient.Update().Index(ENTRY_INDEX).Type(ENTRY_TYPE).Id(entryID).
        Script(script).
        Do(ctx)

    if err != nil {return err}

    return nil
}

You can see more information about the package with GoDoc or by looking through the source code.

答案2

得分: 0

以下代码应该解决这个问题

_, err = eclient.Update().Index(INDEX).
Type(TYPE).
Id(ID).
Doc(map[string]interface{}{field: message}).
Do(ctx)

英文:

The following code should resolve the issue

_, err = eclient.Update().Index(INDEX).
Type(TYPE).
Id(ID).
Doc(map[string]interface{}{field: message}).
Do(ctx)

答案3

得分: 0

Credit where it's due Gavin's answer put me on the right track. This is for another .Index but the full function that acts as a generic single field update is as follows:

func UpdateUser(eclient *elastic.Client, userID string, field string, newContent interface{}) error {
    //CHANGES A SINGLE FIELD OF ES USER DOCUMENT(requires an elastic client pointer,
    //    the user DocID, the field you wish to modify as a string,
    //    and what you want to change that field to as any type necessary)
    //RETURN AN error IF SUCCESSFUL error = nil

    ctx := context.Background()

    exists, err := eclient.IndexExists(USER_INDEX).Do(ctx)
    if err != nil {
        return err
    }
    if !exists {
        return errors.New("Index does not exist")
    }

    _, err = eclient.Update().
        Index(USER_INDEX).
        Type(USER_TYPE).
        Id(userID).
        Doc(map[string]interface{}{field: newContent}).
        Do(ctx)

    return nil
}

You can change the .Index, .Type, and .Id and it works with all fields and types as far as I can tell.

英文:

Credit where it's due Gavin's answer put me on the right track. This is for another .Index but the full function that acts as a generic single field update is as follows:

func UpdateUser(eclient *elastic.Client, userID string, field string, newContent interface{})error {
	//CHANGES A SINGLE FIELD OF ES USER DOCUMENT(requires an elastic client pointer,
	//	the user DocID, the feild you wish to modify as a string,
	//	and what you want to change that field to as any type necessary)
	//RETURN AN error IF SUCESSFUL error = nil

	ctx := context.Background()

	exists, err := eclient.IndexExists(USER_INDEX).Do(ctx)
	if err != nil {return err}
	if !exists {return errors.New("Index does not exist")}

	_, err = eclient.Update().
		Index(USER_INDEX).
		Type(USER_TYPE).
		Id(userID).
    	Doc(map[string]interface{}{field: newContent}).
		Do(ctx)


    return nil
}

You can change the .Index, .Type, and .Id and it works with all fields and types as far as I can tell

huangapple
  • 本文由 发表于 2017年8月24日 05:00:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/45849186.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定