Удаление объекта из вложенного массива в DynamoDB - AWS JavaScript SDK - PullRequest
2 голосов
/ 18 июня 2020

Я создаю приложение, в котором мне нужно удалить элементы, хранящиеся в базе данных. Вот (сокращенный) пример пользовательских данных, которые у меня есть в моей таблице DynamoDB под названием «RegisterUsers»:

{
  "userId": "f3a0f858-57b4-4420-81fa-1f0acdec979d"
  "aboutMe": "My name is Mary, and I just love jigsaw puzzles! My favourite jigsaw category is Architecture, but I also like ones with plants in them.",
  "age": 27,
  "email": "mary_smith@gmail.com",
  "favourites": {
    "imageLibrary": [
      {
        "id": "71ff8060-fcf2-4523-98e5-f48127d7d88b",
        "name": "bird.jpg",
        "rating": 5,
        "url": "https://s3.eu-west-2.amazonaws.com/jigsaw-image-library/image-library/images/bird.jpg"
      },
      {
        "id": "fea4fd2a-851b-411f-8dc2-1ae0e144188a",
        "name": "porsche.jpg",
        "rating": 3,
        "url": "https://s3.eu-west-2.amazonaws.com/jigsaw-image-library/image-library/images/porsche.jpg"
      },
      {
        "id": "328b913f-b364-47df-929d-925676156e97",
        "name": "rose.jpg",
        "rating": 0,
        "url": "https://s3.eu-west-2.amazonaws.com/jigsaw-image-library/image-library/images/rose.jpg"
      }
    ]
  }
}

Я хочу иметь возможность удалить элемент rose.jpg в массиве user.favourites.imageLibrary. Чтобы выбрать правильного пользователя, я могу указать userId в качестве первичного ключа. Затем, чтобы выбрать правильное изображение в массиве, я могу передать AWS.DocumentClient id элемента, чтобы удалить его. Однако у меня возникли проблемы с пониманием справочной документации по AWS API. Примеры, приведенные в руководстве разработчика, не описывают, как удалить элемент, просмотрев один из его атрибутов. Я знаю, что должен предоставить объекты UpdateExpression и ExpressionAttributeValues. Когда я хотел изменить настройки пользователя, мне было довольно легко сделать:

const params = {
    TableName: REGISTERED_USERS_TABLE,
    Key: { userId },
    UpdateExpression: "set userPreferences.difficulty.showGridOverlay = :d",
    ExpressionAttributeValues: {
      ":d": !showGridOverlay
    },
    ReturnValues: "UPDATED_NEW"
  };

В заключение, мне нужен подходящий объект Key, UpdateExpression и ExpressionAttributeValues ​​для доступа к элементу rose.jpg в массиве избранного. .

1 Ответ

2 голосов
/ 21 июня 2020

К сожалению, синтаксис UpdateExpression не такой мощный, как вам хотелось бы. Он поддерживает целые вложенные документы внутри элемента, но не сложные выражения для поиска в них или их изменения. Единственная возможность, которую он дает вам внутри списка, - это доступ или изменение его N-го элемента. Например:

REMOVE #favorites.#imagelibrary[3]

Удалит 3-й элемент библиотеки imagelibrary (обратите внимание, что «#imagelibrary» нужно будет определить в ExpressionAttributeNames), и вы также можете иметь условие для #favorites.#imagelibrary[3].#id , например, в ConditionExpression. Но, к сожалению, нет способа указать более сложные комбинации условий и обновлений, такие как «найди мне i, где # избранное. # Imagelibrary [i]. # Id равно что-то, а затем УДАЛИТЬ этот конкретный c элемент» .

Ваш оставшийся вариант - прочитать полное значение элемента (или с ProjectionExpression только массив #favorties.#imagelibrary), а затем в своем собственном коде найти, какой из элементов вы хотите удалить (например, , обнаружите, что это 3-й элемент), а затем в отдельном обновлении удалите 3-й элемент.

Обратите внимание, что если есть вероятность, что какая-то другая параллельная операция также изменит элемент, вы должны использовать условное обновление (как UpdateExpression, так и ConditionExpression) для удаления элемента, чтобы убедиться, что удаляемый элемент по-прежнему имеет ожидаемый идентификатор. Если условие не выполняется, вам нужно повторить всю операцию снова - прочитать измененный элемент еще раз, снова найти элемент и снова попытаться удалить его. Это пример так называемого метода блокировки optimisti c, который часто используется с DynamoDB.

...