0
votes

I have a table in DynamoDB called 'tasks'. This is an example of what a task in 'tasks' looks like:

{
    "taskId": "e3b8d901-6d74-4caa-9360-5b2f7aaec513",
    "notes": [
        {
            "noteId": "aeeeeb60-3221-4d4e-b362-d63b48f42fba",
            "text": "thing to do next and words",
            "status": "TODO"
        },
        {
            "noteId": "88eeeb60-3221-4d4e-b362-d63b48f42fba",
            "text": "other text and stuff",
            "status": "QUESTION"
        }
    ],
    "title": "Some Task"
}

I would like to delete a note from a task. To delete a task has been simple- I use the taskId as the key. However, I'm not sure how to use the key when accessing a nested item in an array, and I haven't been able to figure it out from the docs.

This is what my route looks like:

api.delete('/tasks/{id}/notes/{noteId}', (request) => {

  return deleteNote(request.pathParams.id, request.pathParams.noteId)
}, {
  error: 400
})

And this is how I'm trying to delete a note in DynamoDB:

function deleteNote(taskId, noteId){

  return docClient.delete({
    TableName: 'tasks',
    Key: {
      noteId: noteId
    }
  }).promise()
    .then((res) => {
      console.log('Note deleted!', res)
      return res
    })
    .catch((error) => {
      console.log('Note not deleted', error);
      throw error
    })
}

Of course, this doesn't work because noteId is not a top-level partition key. How can I filter the tasks for the right one, then filter note notes for the right one? I have an idea of how to do that with JavaScript, but not in DynamoDB.

Thanks!

UPDATE TO ADD:

As Pari has pointed out below, this should really be an update to a task, not a delete. Here's how I modified my 'edit task' to include notes, but I get the error: "The provided expression refers to an attribute that does not exist in the item".

My thinking of how I've done it below is that the whole updated notes array (the array with the one note I want to delete removed) would replace the notes array.

function editTask(taskId, updatedTask){
  if (!taskId || !updatedTask) {
    throw new Error('Insufficient infromation to update task')
  }

  return docClient.update({
    TableName: 'tasks',
    Key: {
      taskId: taskId
    },
    UpdateExpression: 'set title = :t, set notes = :n',
    ExpressionAttributeValues: {
      ':t': updatedTask.title,
      ':n': updatedTask.notes
    },
    ReturnValues: 'ALL_NEW'
  }).promise()
    .then((res) => {
      console.log('Task updated!', res)
      return res
    })
    .catch((error) => {
      console.log('Task not updated', error);
      throw error
    })
}
3

3 Answers

0
votes

Please Update your UpdateExpression with :

UpdateExpression: 'SET title = :t, notes = :n',

0
votes

Technically the Notes are not their own table, so deleting them would require you to update the document "Task" without the note you don't want. So I would recommend updating the instead of deleting the document. So perform a get on that Task with that Id as you are doing, and then use the .filter method and remove that element with splice. Then perform a .put instead of .delete with that id. Im sure there is a way to do this with params.

0
votes

So after looking at it a little more, I saw a couple of java examples achieve this. Have you tried with update instead of delete?

api.get('/tasks/{id}/notes/{nodeId)',(req,res)=>{
    let id = req.params.id;
    let noteId = req.params.noteId;
   updateTask(id, noteId);
    


})



function updateTask(id, noteId){

    return docClient.update({
      TableName: 'tasks',
      Key: {
        noteId: noteId
      }
    }).promise()
      .then((res) => {
        console.log('Note deleted!', res)
        return res
      })
      .catch((error) => {
        console.log('Note not deleted', error);
        throw error
      })
  }