如何使用AWS Go SDK仅更新DynamoDB中的单个字段



希望有人能给我一些启示,我一直在想这个问题。

我在Dynamo中有这个表,我们称之为people,在这个表中,我有id的属性作为我们的分区键,name,lastNamestatus。我希望能够只是更新单个属性或所有的保存ID。现在,我是这样做的。我创建了以下结构体:

type PersonUpdate struct {
FirstName     string `json:"firstName,omitempty"`
LastName      string `json:"lastName,omitempty"`
Status        string `json:"status,omitempty"`
}

来自服务器的请求将只是更新该人的姓氏,所以我们的请求体看起来如下:

{
"lastName": "bob"
}

将请求绑定到结构体后,将发送给dynamo的对象如下所示:

{
"firstName": "",
"lastName": "bob",
"status": "",
}

现在,当你写dynamo的时候,你可以看到,只有一个属性应该更新,而其余的空/null应该被忽略。

执行此操作的代码可以浓缩为以下操作:

// Marshal our object
_, err := dynamodbattribute.MarshalMap(person)
if err != nil{
fmt.Println("some error marshaling")
}
// Create our update input
input := &dynamodb.UpdateItemInput{
key: map[string]*dynamodb.AttributeValue{
"id":{
S: aws.String("1234"),
},
},
TableName: aws.String("people"),
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":fn": {
S: aws.String(person.FirstName),
},
":ln":{
S: aws.String(person.LastName),
},
":st":{
S: aws.String(person.Status),
},
},
UpdateExpression: aws.String("set firstName = :fn, lastName = :ln, status = :st"),
ReturnValues: aws.String("UPDATED_NEW"),
}
// Send update request to Dynamo
_, err := service.UpdateItem(input)

现在,更新没有问题,问题是firstNamestatus的值为空也被传递了。我试着去看他们的文件,但还是有点困惑。我知道一个事实,Java SDK允许你传递一个名为UPDATE_SKIP_NULL_ATTRIBUTES的标志,它允许你跳过那些空值,只更新那些有数据的。我不知道在Go中什么是等价的,任何帮助/指导都会很棒。

更新:

尝试使用以下模型:

type UserModel struct {
FirstName string `json:"firstName,omitempty" dynamodbav:"firstName,omitempty"`
LastName  string `json:"lastName,omitempty" dynamodbav:"lastName,omitempty"`
}

遵循@jarmod和@fedonev给出的建议。从逻辑上和使用文档可以理解为什么这应该工作,不幸的是,它没有

决定将SDK从V1切换到V2,看看是否可能更新它会有所帮助,虽然我在同一个洞。这是我的更新函数。

update :=expression.Set(expression.Name("firstName"),expression.Value(user.FirstName))
update.Set(expression.Name("lastName"), expression.Value(user.LastName))
expr, err := expression.NewBuilder().WithUpdate(update).Build()
if err != nil {
"log error here..."
}
_, err = svc.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
TableName:                 aws.String("people"),
Key:                       map[string]types.AttributeValue{"id": id},
ExpressionAttributeNames:  expr.Names(),
ExpressionAttributeValues: expr.Values(),
UpdateExpression:          expr.Update(),
ReturnValues:              types.ReturnValueUpdatedNew,
})
if err != nil {
"log error here..."
}

我最终通过编写一个查询和创建函数来解决我的问题,该函数通过我们想要更新的JSON有效负载中的ID进行查询,并根据我们需要更新的内容对查询进行区分,并且任何空字段都被查询结果取代。到目前为止,它解决了我的问题,但我仍然想知道如何去做一个更新使用其预期的功能。

正如@jarmod的注释所说,在封送结构时应用dynamodbav:",omitempty"标记跳过零值字段:

type PersonUpdate struct {
FirstName     string `json:"firstName,omitempty" dynamodbav:",omitempty"`
LastName      string `json:"lastName,omitempty" dynamodbav:",omitempty"`
Status        string `json:"status,omitempty" dynamodbav:",omitempty"`
}

[Edit: add usage]MarshalMap现在将忽略零值字段,尊重标签。遍历映射以构造更新表达式:

av, _ := attributevalue.MarshalMap(person)
update := expression.UpdateBuilder{}
for k, v := range av {
update = update.Set(expression.Name(k), expression.Value(v))
}

构建表达式并将其输出传递给UpdateItem,如op。

相关内容

  • 没有找到相关文章

最新更新