3

I'm building an app where I need to delete items stored in the database. Here's a (shortened) example of user data I have in my DynamoDB table called 'registeredUsers':

{
  "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": "[email protected]",
  "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"
      }
    ]
  }
}

I want to be able to delete the item 'rose.jpg' in the user.favourites.imageLibrary array. In order to select the correct user, I can provide the userId as the primary key. Then, in order to select the correct image in the array, I can pass the AWS.DocumentClient the 'id' of the item in order to delete it. However, I'm having trouble understanding the AWS API Reference docs. The examples given in the developer guide do not describe how to delete an item by looking at one of it's attributes. I know I have to provide an UpdateExpression and an ExpressionAttributeValues object. When I wanted to change a user setting, I found it pretty easy to do:

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

To conclude, I need a suitable Key, UpdateExpression and ExpressionAttributeValues object to access the rose.jpg item in the favourites array.

1
  • hi were you able to achieve that ? can you please share Commented Dec 31, 2021 at 5:25

1 Answer 1

4

Unfortunately, the UpdateExpression syntax is not as powerful as you would have liked. It supports entire nested documents inside the item, but not sophisticated expressions to search in them or to modify them. The only ability it gives you inside a list is to access or modify its Nth element. For example:

REMOVE #favorites.#imagelibrary[3]

Will remove the 3rd element of imagelibrary (note that the "#imagelibrary" will need to be defined in ExpressionAttributeNames), and you can also have a condition on #favorites.#imagelibrary[3].#id, for example, in ConditionExpression. But unfortunately, there is no way to specify more complex combinations of conditions and updates, such as "find me the i where #favorites.#imagelibrary[i].#id is equal something, and then REMOVE this specific element".

Your remaining option is to read the full value of the item (or with ProjectionExpression just the #favorties.#imagelibrary array), and then in your own code find which of the elements you want to remove (e.g., discover that it is the 3rd element), and then in a separate update, remove the 3rd element.

Note that if there's a possibility that some other parallel operation also changes the item, you must use a conditional update (both UpdateExpression and ConditionExpression) for the element removal, to ensure the element that you are removing still has the id you expected. If the condition fails, you need to repeat the whole operation again - read the modified item again, find the element again, and try to remove it again. This is an example of the so-called "optimistic locking" technique which is often used with DynamoDB.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the detailed response. I’ve done what you suggested and updated the entire favourite.imageLibrary map with its content minus the image I want to delete. I will look into the optimistic locking technique as this is something I may have to consider in future. Thanks again!
Note that in this case, you don't need to use a full-blown "optimistic locking" technique involving additional version numbers - you can do what I suggested where you figure out that you want to remove the 3rd image, and then just do a conditional update: "remove the 3rd image but only if its id still equals xyz123". This will give you almost-free concurrency safety (conditional updates don't cost more than non-conditional updates in DynamoDB).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.