Reputation: 143
Edit Issue: I get error 400 when trying to update my map[]interface field.
I'm stuck on updating my array object in DynamoDB when using UpdateItem, specifically on my array object (in this case Authors field).
&awserr.requestError{awsError:(*awserr.baseError)(0xc000204140), statusCode:400, requestID:"QU2MMAJVDRM0JHJEPOE93VJPSVVV4KQNSO5AEMVJF66Q9ASUAAJG", bytes:[]uint8(nil)}
I did not encounter any problems when using PutItem with the same struct. I'm not sure what I'm missing and the error AWS is giving out is not that clear for me.
Struct:
type Book struct {
Id int `json:":id"`
Title string `json:":title"`
Photo Photo `json:":photo"`
Authors []Author `json:":authors"`
}
type Author struct {
Id int `json:":id"`
Name string `json:":name"`
}
I already tried Update Code:
input := &dynamodb.UpdateItemInput{
TableName: aws.String("books"),
Key: key,
UpdateExpression: aws.String(updateExp),
ExpressionAttributeValues: value,
}
Update expression:
"SET title = :title, photo = :photo, authors = list_append(authors, :authors)"
I also already tried
authors = :authors
Since I plan on replacing the whole Authors value every time anyway, but I just can seem to get this work.
When I log my ExpressionAttributeValue it looks like this
ExpressionAttributeValues: {
:authors: {
L: [{
M: {
id: {
N: "1"
},
name: {
S: "Bob"
}
}
},{
M: {
name: {
S: "Arthur"
},
id: {
N: "2"
}
}
}]
},
:title: {
S: "Jumanji"
},
:description: {
S: "Jungle Book"
},
:photo: {
M: {
original: {
S: "sample.jpg"
}
}
}
}
I have already tested removing the authors field update (coded in such a way that UpdateExpression adjusts depending on available data) and all other field updates work fine, so my problem is really just for updating []struct type.
Upvotes: 1
Views: 3935
Reputation: 954
I understand the issue is about how to update an entire array using updateItem. I was having similar issue (this is how I found your question) but I managed to solve it on my own because there is no much to find about updating arrays with DynamoDB. I kept this browser's tab open for when I got it done, and now I can provide some useful help:
So, you wanted to update your authors array (along with others such as title, description and photo). Say your "authors" look like this:
const authors = [
{
id: 1,
name: "Bob"
},
{
id: 2,
name: "Arthur"
}
];
I would first run a for-loop to properly map the data for the update, because you could have much more than just two items in the array. Like this:
const authArray = []
for (const a of authors) {
authArray.push({ M: {
id: { N: a.id.toString() }, // if id is type number, must convert to string
name: { S: a.name }
} });
}
Then we prepare the update:
const params = {
TableName: 'your-table-name',
Key: { "UserID": { S: userID } },
ExpressionAttributeValues: {
":au": { L: authArray },
":ti": { S: "Jumanji" },
":de": { S: "Jungle Book" },
":ph": { M: { original: { S: "sample.jpg" } }
},
ExpressionAttributeNames: {
"#A": "authors",
"#T": "title",
"#D": "description",
"#P": "photo"
},
UpdateExpression:
"SET #A=:au, #T=:ti, #D=:de, #P=:ph",
ReturnValues:
"ALL_NEW"
}
dynamoDB.updateItem(params, function (err, item) {
if (err) {
console.log('UPDATE FAILED! => ', err);
cb(err);
} else {
console.log('SUCCESS UPDATE! => ', item);
item = item.Attributes;
cb(null, item);
}
I hope this good enough for you. It worked for me.
Upvotes: 6