如何使用文档客户端

时间:2018-02-01 12:39:33

标签: javascript amazon-dynamodb

我有一个DynamoDB表,其中表中的每个项都有一个注释数组作为属性。我的架构看起来像这样:

{
  "id": "abc",
  "name": "This is an item"
  "comments": [
    "commentId": "abcdefg",
    "commentAuthor": "Alice",
    "commentDetails": "This item is my favourite!"
  ]
}

我希望能够通过commentId编辑单个注释,但是不清楚如何为此更新编写DynamoDB表达式(我正在使用DocumentClient)。

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

4 个答案:

答案 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
});

输出:

enter image description here

答案 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",
        }