AWS DynamoDB DocumentClient 查询错误 - 一个或多个参数值无效:条件参数类型与架构类型不匹配

AWS DynamoDB DocumentClient query error - One or more parameter values were invalid: Condition parameter type does not match schema type

我有一个名为 AccountXX 的 AWS DynamoDb table,它将具有 JSON 结构的项目存储为:

{
  "id": "some id value", // also the partition key for the table
  "name": "a name",
  "email": "an email address",
  "salt": [12, 3, ... ], // an array of random values
  "hash": [1, 5, ... ],  // an array representing a hashed password
  ... // and some more attributes
}

AccountXX table 上有一个名为 Account_email_hash_salt_gsi 的全局二级索引,它具有分区键 email 并具有附加属性 hash, saltid.

当我发出以下 AWS CLI 命令时,我能够成功查询 table 中的项目:

aws dynamodb query --table AccountXX 
  --index-name Account_email_hash_salt_gsi 
  --key-condition-expression "email = :emailValue" 
  --expression-attribute-values file://values.json

values.json的内容是:

{":emailValue":{"S": "someone@somewhere.in"}}

但是,当我使用以下参数对象使用 AWS.DynamoDB.DocumentClient 实例发出类似调用时,出现错误:

  const params = {
    TableName: accountTable,       // will be set to 'AccountXX'
    IndexName: "Account_email_hash_salt_gsi",
    KeyConditionExpression:"#email = :emailValue",
    ExpressionAttributeNames: {
        "#email": "email"
    },
    ExpressionAttributeValues: {
        ":emailValue": {"S": loginToken.email}
    },
    ScanIndexForward: false
  };

我得到的错误是:

ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type
    at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)

我也尝试使用修改后的参数对象如下:

  const params = {
    TableName: accountTable,   // will be set to 'AccountXX'
    IndexName: "Account_email_hash_salt_gsi",
    KeyConditionExpression:"#email = :emailValue",
    ExpressionAttributeNames: {
        "#email": "email"
    },
    ExpressionAttributeValues: {
        ":emailValue": loginToken.email   // directly using string type
    },
    ScanIndexForward: false
  };

在这种情况下,我得到以下错误:

ValidationException: ExpressionAttributeValues must not be empty
    at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)

在这两种情况下,我的 DynamoDB DocumentClient 查询发出为:

const data = await dynamo.query(params).promise();

我应该怎么做才能修复 params 对象,以便我能够成功查询 table?

找到并解决了问题。问题不在于 DynamoDB 查询或参数构造。 根本原因是 Lambda 传递 POST 请求主体和处理程序错误处理它的问题。 处理程序缺少 JSON.parse(event.body),因此 loginToken 是一个字符串。因此 loginToken.email 评估为空导致查询失败。

顺便说一句,我发现 Amazon NoSQL Workbench tool that was mentioned in 对于探索查询和使用 UI 自动生成它们非常有帮助。我用它来确保查询参数在语法上是正确的,然后在进行一些故障排除后能够找到根本原因。