Search code examples
amazon-dynamodbaws-step-functions

How can I use an input value in the ExpressionAttributeNames section of a DynamoDB Step Function task?


I'm trying to use a DynamoDB resource within a Step Function, and I'm unable to use a value from the step's input within ExpressionAttributeValues.

Here's my record before running the step function:

{
  "groupId": "5c9e4c4e-088c-48bb-9e41-8d7b6227f117",
  "invitationStatus": {
    "johndoe@example.com": "unsent"
  }
}

Here's the input to the step:

{
  "email": "johndoe@example.com",
  "groupId": "5c9e4c4e-088c-48bb-9e41-8d7b6227f117"
}

Here's my step definition:

"Mark Invitation Sent": {
  "Comment": "Marks an invitation as having been sent",
  "Type": "Task",
  "Resource": "arn:aws:states:::dynamodb:updateItem",
  "Parameters": {
    "TableName": "[my-table-name]",
    "Key": {
      "groupId": {
        "S.$": "$.groupId"
      }
    },
    "UpdateExpression": "SET invitationStatus.#email = :sent",
    "ExpressionAttributeNames": {
      "#email": "$.email"
    },
    "ExpressionAttributeValues": {
      ":sent": {
        "S": "sent"
      }
    }
  },
  "End": true
}

And here's the record after running the step:

{
  "groupId": "5c9e4c4e-088c-48bb-9e41-8d7b6227f117",
  "invitationStatus": {
    "$.email": "sent",
    "johndoe@example.com": "unsent"
  }
}

As you can see, it's using the literal value of "$.email" instead of the actual value (johndoe@example.com). What am I doing wrong?


Solution

  • Found my answer at https://states-language.net/spec.html#parameters:

    When a field name ends with “.$” and its value can be used to generate an Extracted Value as described above, the field is replaced within the Parameters value by another field whose name is the original name minus the “.$” suffix, and whose value is the Extracted Value.

    Which basically means I needed to change "#email" to "#email.$". Making that change to my step definition like this fixed my problem:

    "Mark Invitation Sent": {
      "Comment": "Marks an invitation as having been sent",
      "Type": "Task",
      "Resource": "arn:aws:states:::dynamodb:updateItem",
      "Parameters": {
        "TableName": "[my-table-name]",
        "Key": {
          "groupId": {
            "S.$": "$.groupId" //This is where I should have realized I already had an example of something that works
          }
        },
        "UpdateExpression": "SET invitationStatus.#email = :sent",
        "ExpressionAttributeNames": {
          "#email.$": "$.email" //This is the only changed line
        },
        "ExpressionAttributeValues": {
          ":sent": {
            "S": "sent"
          }
        }
      },
      "End": true
    }