我有一个DynamoDB表,其中表中的每个项都有一个注释数组作为属性。我的架构看起来像这样:
{
"id": "abc",
"name": "This is an item"
"comments": [
"commentId": "abcdefg",
"commentAuthor": "Alice",
"commentDetails": "This item is my favourite!"
]
}
我希望能够通过commentId
编辑单个注释,但是不清楚如何为此更新编写DynamoDB表达式(我正在使用DocumentClient)。
我们如何在Dynamo中更新嵌入式阵列中的条目?是否可以通过数组索引或查询表达式进行更新?
答案 0 :(得分:7)
我认为应该对您的数据模型进行一些修改。您应该使用dynamodb map,只需将您的commentId作为访问每条评论的关键
{
"id": "abc",
"name": "This is an item"
"comments": {
"abcdefg":{
"commentAuthor": "Alice",
"commentDetails": "This item is my favourite!"
}
}
}
然后查询看起来像这样,你必须知道两件事来更新评论1是项目ID而2是评论ID
var params = {
TableName: Tablename,
Key: {id: "abc"},
UpdateExpression:"set comments.#abcdefg.commentDetails=:val1",
ExpressionAttributeNames: {
"#abcdefg":"abcdefg"
},
ExpressionAttributeValues:{
":val1":"New comment text"
}
}
db.update(param,callback);
请让我知道并原谅我,解释你的问题,如果我误解,因为我没有足够的分数来澄清我对评论的怀疑。
答案 1 :(得分:4)
就个人而言,我不会把我想编辑或频繁访问的项目放在远离主键的位置。记住DynamoDB基本上是一个键值存储,所以每当你想访问东西时,最好通过主键暴露这些项目。
那么你能做些什么,在我看来,最好的方法是略微改变你的数据模型。所以我会创建一个包含主键ID和项类型排序键的表。在您的情况下,您现在将有两种项目类型,“项目”和“comment_ [commentID]”。 每个注释都可以将作者和详细信息字段作为其属性,如下所示:
- [ID - ITEMTYPE] - NAME
- "abc" - "item" - "This is an item"
- [ID - ITEMTYPE] - AUTHOR - DETAILS
- "abc" - "comment_abcdefg" - "Alice" - "This item is my favourite!"
现在,如果您想获取项目的所有评论,只需查询项目ID,并使用“评论”开头的排序键。如果您想编辑评论,您可以通过将该ID添加到排序键来获得此项目,这将导致完全匹配。 (这也非常快)。 有几种方法可以让你更灵活,但这应该足以满足你的要求。
很抱歉,我只是读了你对另一个答案的评论,当然,你可以在评论和项目类型sortkey中的ID字段之间添加一个排序编号,这样评论会按顺序自动排序(或反向)当然)。
答案 2 :(得分:2)
是否可以按数组索引更新...?
是的,如果您知道索引,那就非常easy。刚刚在我当地localhost:8000/shell/
为我工作。我假设comments
列表中的每个注释元素都是一个对象,并且您忘记了示例中注释属性周围的括号{}
。如果我误解或者您的需求更多,请告诉我。
var params = {
TableName: 'table_name',
Key: { // The primary key of the item (a map of attribute name to AttributeValue)
id: 'abc', //(string | number | boolean | null | Binary)
// more attributes...
},
UpdateExpression: 'SET comments[1] = :value', // String representation of the update to an attribute
// SET set-action , ...
// REMOVE remove-action , ... (for document support)
// ADD add-action , ...
// DELETE delete-action , ... (previous DELETE equivalent)
ExpressionAttributeValues: { // a map of substitutions for all attribute values
':value': {
commentId: 'abcdefg1',
commentAuthor: 'Alice',
commentDetails: 'changed'
}
},
ReturnValues: 'NONE', // optional (NONE | ALL_OLD | UPDATED_OLD | ALL_NEW | UPDATED_NEW)
ReturnConsumedCapacity: 'NONE', // optional (NONE | TOTAL | INDEXES)
ReturnItemCollectionMetrics: 'NONE', // optional (NONE | SIZE)
};
docClient.update(params, function(err, data) {
if (err) ppJson(err); // an error occurred
else ppJson(data); // successful response
});
答案 3 :(得分:1)
这是我用来从UsersCategoryTable中停用用户的方式:
const userIdx = users.map(user => user.M.id.S).indexOf(userId)
const deactivateUserParams = {
TableName: USERS_CATEGORY_TABLE_DEV,
Key: {id: {S: catId}},
UpdateExpression: `SET updatedAt = :updated_at, #users[${userIdx}].#status = :new_status`,
ExpressionAttributeNames: {
"#users": 'users',
"#status": "status"
},
ExpressionAttributeValues: {
":new_status": {"S": "INACTIVE"},
":updated_at": {"S": new Date().toISOString()}
},
ReturnValues: "UPDATED_NEW",
}