Javascript 如何使用文档客户端修改dynamodb中嵌入列表中的元素

Javascript 如何使用文档客户端修改dynamodb中嵌入列表中的元素,javascript,amazon-dynamodb,Javascript,Amazon Dynamodb,我有一个DynamoDB表,表中的每个项都有一个注释数组作为属性。我的模式如下所示: { "id": "abc", "name": "This is an item" "comments": [ "commentId": "abcdefg", "commentAuthor": "Alice", "commentDetails": "This item is my favourite!" ] } - [ID - ITEMTYPE] -

我有一个DynamoDB表,表中的每个项都有一个注释数组作为属性。我的模式如下所示:

{
  "id": "abc",
  "name": "This is an item"
  "comments": [
    "commentId": "abcdefg",
    "commentAuthor": "Alice",
    "commentDetails": "This item is my favourite!"
  ]
}
- [ID    - ITEMTYPE]         - NAME
- "abc"  - "item"            - "This is an item"
- [ID    - ITEMTYPE]         - AUTHOR  - DETAILS
- "abc"  - "comment_abcdefg" - "Alice" - "This item is my favourite!"
我希望能够通过其
commentId
编辑单个注释,但不清楚如何为此更新编写DynamoDB表达式(我使用的是DocumentClient)


如何在Dynamo中更新嵌入式数组中的条目?是否可以通过数组索引或查询表达式进行更新?

我认为应该对您的数据模型进行一些修改。您应该为此使用dynamodb映射,只需将您的commentId作为访问每个注释的键即可

 {
  "id": "abc",
  "name": "This is an item"
  "comments": {
    "abcdefg":{
      "commentAuthor": "Alice",
      "commentDetails": "This item is my favourite!"
    }
  }
}
然后查询看起来像这样,您必须知道两件事来更新注释1是Item id,2是comment 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);

请让我知道,请原谅,如果我误解了您的问题,请解释,因为我在评论中没有足够的要点来澄清我的疑问。

就我个人而言,我不会将我想要编辑或访问的项目经常放在离主键这么远的地方。请记住,DynamoDB基本上是一个键值存储,所以每当您想要访问内容时,最好通过主键公开这些项目

因此,在我看来,最好的方法是稍微修改一下数据模型,你能做些什么呢。所以我将创建一个带有主键ID和项类型的排序键的表。在您的例子中,现在有两种项目类型,“item”和“comment.[commentID]”。 每个注释都可以将author和details字段作为其属性,如下所示:

{
  "id": "abc",
  "name": "This is an item"
  "comments": [
    "commentId": "abcdefg",
    "commentAuthor": "Alice",
    "commentDetails": "This item is my favourite!"
  ]
}
- [ID    - ITEMTYPE]         - NAME
- "abc"  - "item"            - "This is an item"
- [ID    - ITEMTYPE]         - AUTHOR  - DETAILS
- "abc"  - "comment_abcdefg" - "Alice" - "This item is my favourite!"
现在,如果您想获取某个项目的所有注释,只需使用排序键以“comment”开头查询项目ID即可。如果要编辑注释,只需将ID添加到排序键即可获得该项,这将导致精确匹配。(这也会非常快)。 有几种方法可以让这变得更加灵活,但这应该足以满足您的要求

很抱歉,我刚刚读了你对另一个答案的评论,当然,你可以在评论和条目类型sortkey中的ID字段之间添加一个排序号,这样评论会自动按该顺序排序(或反向)

是否可以通过数组索引进行更新

是的,如果你知道索引的话,那就相当不错了。这在我的本地
localhost:8000/shell/
中对我起了作用。我假设
comments
列表中的每个comment元素都是一个对象,并且您忘记了示例中comment属性周围的括号
{}
。请让我知道如果我误解或如果有更多的你的需要

var参数={
TableName:“table_name”,
Key:{//项的主键(属性名到AttributeValue的映射)
id:'abc',/(字符串|数字|布尔|空|二进制)
//更多属性。。。
},
UpdateExpression:'设置注释[1]=:值',//属性更新的字符串表示形式
//设定动作。。。
//删除操作,…(用于文档支持)
//添加操作。。。
//删除操作,…(以前的删除等效)
ExpressionAttributeValues:{//所有属性值的替换映射
“:值”:{
commentId:'abcdefg1',
评论作者:《爱丽丝》,
commentDetails:“已更改”
}
},
returnValue:'NONE',//可选(NONE | ALL|u OLD | UPDATED|u OLD | ALL|u NEW | UPDATED|u NEW)
ReturnConsumedCapacity:'无',//可选(无|总|索引)
ReturnItemCollectionMetrics:'无',//可选(无|大小)
};
更新(参数,函数(错误,数据){
if(err)ppJson(err);//发生错误
else ppJson(数据);//响应成功
});
输出:

这是我用来从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",
        }


谢谢你的回答。这似乎是可行的,也是我考虑过的一种选择,但“地图”并没有真正提供与阵列相同的功能。例如,排序对于注释的注册时间很重要,因此将新项推送到数组是有意义的。尽管如此,还是有一些方法可以解决这个问题。AFAIK如果您想对阵列而不是映射执行此操作,您必须拆下整个阵列,进行所需的更改,然后用新版本的阵列替换该阵列。从数据库设计的角度来看,如果您一直使用Dynamo,那么伪造一个关系可能更有意义,您只需将注释id存储在一个数组中,并将注释存储在它们自己的表中。我认为最好的方法是使用@saurabh yadav建议的映射,并使用二级索引,以保持注释的排序,正如这里所讨论的@jaredkwright“好吧,如果你想对数组而不是映射执行此操作,你必须拆下整个数组,进行所需的更改,并用新版本的数组替换该数组”——我在回答中演示的查询与此相反。