通过步骤函数在 DynamoDB 的 putItem 中存储可选属性

Storing optional attributes in DynamoDB's putItem via step functions

我在 AWS 步骤函数中定义了一个状态机,我的状态之一是将项目存储到 DynamoDB

...
"Store item": {
  "End": true,
  "Type": "Task",
  "Resource": "arn:aws:states:::dynamodb:putItem",
  "Parameters": {
    "Item": {
      "foo": {
        "S.$": "$.data.foo"
      },
      "bar": {
        "S.$": "$.data.bar"
      },
      "baz": {
        "S.$": "$.data.baz"
      },
    },
    "TableName": "nrp_items"
  }
},
...

问题源于 baz 属性 是可选的,即在某些情况下不存在。 在这些情况下,putItem 任务失败:

An error occurred while executing the state 'Store item' (entered at the event id #71). > The JSONPath '$.data.baz' specified for the field 'S.$' could not be found in the input

我的备用计划是使用 lambda 执行此类操作,但我可以直接使用步骤函数中的 putItem 任务来执行吗?

我想知道是否:

  1. 可以通过 JSONPath 以某种方式将我的整个 $.data 项目注入“项目”属性,例如:
...
"Store item": {
  "End": true,
  "Type": "Task",
  "Resource": "arn:aws:states:::dynamodb:putItem",
  "Parameters": {
    "Item": "$.data",
    "TableName": "nrp_items"
  }
},
...


2)定义baz属性是optional

TL;DR 我们可以用 "Variable": "$.baz", "IsPresent": true 选择条件来处理可选变量来处理 no-baz 情况。

Amazon States Language spec does not have optional properties: Step Functions will throw an error if $.baz does not exist in the input. We can avoid undefined paths by inserting a two-branch Choice State, one branch of which handles baz-exists cases, the other no-baz cases. Each branch continues with a Pass State that reworks the data input into dynamo-format Item syntax, using Parameters。当 baz 未定义时,put-item 任务的 "Item.$": "$.data"(如您的#1)仅包含 foo-bar,否则包含所有三个。

{
  "StartAt": "HasBazChoice",
  "States": {
    "HasBazChoice": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.baz",
          "IsPresent": true,
          "Next": "MakeHasBazItem"
        }
      ],
      "Default": "MakeNoBazItem"
    },
    "MakeHasBazItem": {
      "Type": "Pass",
      "Parameters": {
        "data": {
          "foo": { "S.$": "$.foo"},
          "bar": { "S.$": "$.bar"},
          "baz": { "S.$": "$.baz"}
        }
      },
      "Next": "PutItemTask"
    },
    "MakeNoBazItem": {
      "Type": "Pass",
      "Parameters": {
        "data": {
          "foo": {"S.$": "$.foo"},
          "bar": {"S.$": "$.bar"}
        }
      },
      "Next": "PutItemTask"
    },
    "PutItemTask": {
      ...
      "Parameters": {
        "TableName": "my-table",
        "Item.$": "$.data"
      }
    },
  }
}

如果您有多个可选字段,您的 lambda 备份计划是更好的选择 - 上述解决方法会变得笨拙。