最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to modify an element in an embedded list in dynamodb with document client - Stack Overflow

programmeradmin0浏览0评论

I have a DynamoDB table where each item in the table has an array of comments as an attribute. My schema looks something like this:

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

I want to be able to edit an individual comment by its commentId, but it's not clear how to write a DynamoDB expression for this update (I'm using DocumentClient).

How can we update an entry in an embedded array in Dynamo? Is it possible to update by array index, or by a query expression?

I have a DynamoDB table where each item in the table has an array of comments as an attribute. My schema looks something like this:

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

I want to be able to edit an individual comment by its commentId, but it's not clear how to write a DynamoDB expression for this update (I'm using DocumentClient).

How can we update an entry in an embedded array in Dynamo? Is it possible to update by array index, or by a query expression?

Share Improve this question edited Mar 2, 2018 at 23:44 Uddhav P. Gautam 7,6263 gold badges51 silver badges67 bronze badges asked Feb 1, 2018 at 12:39 JimJim 4,66916 gold badges53 silver badges80 bronze badges 0
Add a comment  | 

4 Answers 4

Reset to default 8

I think there should be some modification to your data model.You should have used dynamodb map for this just make your commentId as a key to access each comment

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

Then the query would look like this and you must know two things to update the comment 1 is Item id and 2 is 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);

Please Let me know and pardon me,explain your question if i misunderstood as i did not have enough points to clear my doubts in comment.

Personally, I would not put items I want to edit or access frequently this far away from the primary key. Remember DynamoDB is basically a key-value store, so whenever you want to access stuff it's always better to have those items exposed through primary keys.

So what could you do about this, in my opinion, the best way is to slightly alter your data model. So I would create a table with a primary key ID and a sort key of the item type. In your case, you would now have two item types, "Item", and "comment_[commentID]". Each comment could have the author and details fields as its attributes so something like this:

- [ID    - ITEMTYPE]         - NAME
- "abc"  - "item"            - "This is an item"
- [ID    - ITEMTYPE]         - AUTHOR  - DETAILS
- "abc"  - "comment_abcdefg" - "Alice" - "This item is my favourite!"

Now if you want to get all comments for an item you simply query for the item ID with the sort key starts with "comment". If you want to edit a comment you could simply get this item by adding the ID to the sort key which would result in an exact match. (also this would be VERY fast). There are several ways in which you could make this even more flexible but this should be enough to do what you asked for.

So sorry I just read your comment on the other answer, of course, you can add a sorting number in between the comment and the ID field in the item type sortkey this way the comments would sort automatically in that order(or reverse off course).

Is it possible to update by array index...?

Yes, it's quite easy if you know the index. This worked for me in my local localhost:8000/shell/ just now. I assumed that each comment element in the comments list is an object and that you forgot the brackets {} around the comment attributes in your example. Please let me know if I misunderstood or if there's more to your needs.

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

Output:

This is the way I used to deactivate users from a 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",
        }

发布评论

评论列表(0)

  1. 暂无评论