Как изменить элемент во встроенном списке в dynamodb с клиентом документа

У меня есть таблица DynamoDB, где каждый элемент в таблице имеет массив комментариев в качестве атрибута. Моя схема выглядит примерно так:

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

Я хочу, чтобы иметь возможность редактировать отдельный комментарий по его commentId, но не ясно, как написать выражение DynamoDB для этого обновления (я использую DocumentClient).

Как мы можем обновить запись во встроенном массиве в Dynamo? Можно ли обновить индексом массива или выражением запроса?

Ответ 1

Я думаю, что в вашей модели данных должна быть какая-то модификация. Вы должны были использовать карту dynamodb для этого, просто сделайте свой комментарий в качестве ключа для доступа к каждому комментарию

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

Тогда запрос будет выглядеть так, и вы должны знать две вещи, чтобы обновить комментарий. 1 - Идентификатор элемента и 2 - идентификатор комментария.

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

Пожалуйста, дайте мне знать и простите меня, объясните свой вопрос, если я неправильно понял, поскольку у меня не было достаточного количества баллов, чтобы убрать мои сомнения в комментарии.

Ответ 2

Лично я бы не стал помещать элементы, которые я хочу редактировать или часто обращаться к далекому от первичного ключа. Помните, что DynamoDB - это, в основном, хранилище ключей, поэтому всякий раз, когда вы хотите получить доступ к материалам, всегда лучше иметь эти предметы, открытые через первичные ключи.

Итак, что вы можете сделать по этому поводу, на мой взгляд, лучший способ - слегка изменить вашу модель данных. Поэтому я бы создал таблицу с идентификатором первичного ключа и ключом сортировки типа элемента. В вашем случае у вас теперь будут два типа элементов: "Item" и "comment_ [commentID]". В каждом комментарии могут быть поля автора и детали в качестве атрибутов, что-то вроде этого:

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

Теперь, если вы хотите получить все комментарии к элементу, который вы просто запрашиваете для идентификатора элемента, ключ сортировки начинается с "комментария". Если вы хотите отредактировать комментарий, вы можете просто получить этот элемент, добавив идентификатор в ключ сортировки, который приведет к точному совпадению. (также это было бы очень быстро). Существует несколько способов сделать это еще более гибким, но этого должно быть достаточно, чтобы делать то, о чем вы просили.

Извините, я просто прочитал ваш комментарий к другому ответу, конечно, вы можете добавить сортировочный номер между комментарием и полем идентификатора в типе сортировки типа элемента таким образом, чтобы комментарии сортировались автоматически в этом порядке (или отменили курс),

Ответ 3

Можно ли обновить по индексу массива...?

Да, это довольно легко, если вы знаете индекс. Это сработало для меня в локальном локальном localhost:8000/shell/ сейчас. Я предположил, что каждый элемент comments списке 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