【问题标题】:DynamoDB query secondary index ValidationException: Condition parameter type does not match schema typeDynamoDB 查询二级索引ValidationException:条件参数类型与架构类型不匹配
【发布时间】:2018-11-14 12:35:42
【问题描述】:

我正在使用无服务器框架开发 AWS 服务。到目前为止,它有一个表和几个全局二级索引。我正在尝试查询全局二级索引。

查询:

{
    "TableName": "messages-table-dev",
    "IndexName": "roomIndex",
    "KeyConditionExpression": "room = :room",
    "ExpressionAttributeValues": {
        ":room": {
            "S": "everyone"
        }
    }
}

它给出了一个例外——使用 Node.js DynamoDB 客户端,而不是 Node.js DocumentClient

ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type
at Request.extractError (/var/task/node_modules/aws-sdk/lib/protocol/json.js:48:27)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
message: 'One or more parameter values were invalid: Condition parameter type does not match schema type',
code: 'ValidationException',
time: 2018-06-05T05:11:08.899Z,
requestId: '72OROVKI35I3QDO2IJNQH6SIRVVV4KQNSO5AEMVJF66Q9ASUAAJG',
statusCode: 400,
retryable: false,
retryDelay: 35.265782751506215

我从文档中了解到 KeyConditionExpression 必须对分区索引进行相等匹配。在这种情况下,room 字段是roomIndex 全局二级索引的分区索引。根据文档,您使用 ExpressionAttributeValues 数组将值替换为表达式,据我所知,这是正确构造的。

异常消息让我想到查询中提供的值与被查询列的类型之间的类型不匹配。这是正确的解释吗?但事实并非如此——正如您在下面看到的,room 列被定义为字符串的S。因此这是一个字符串比较,应该没问题。

再次 - 我没有使用 DocumentClient。我已经看到很多答案建议通过使用该客户端来简化查询。我没用。

该表在 Serverless serverless.yml 中定义如下:

MessagesDynamoDBTable:
  Type: AWS::DynamoDB::Table
  Properties:
    AttributeDefinitions:
      - AttributeName: messageId
        AttributeType: S
      - AttributeName: room
        AttributeType: S
      - AttributeName: userId
        AttributeType: S
    KeySchema:
      - AttributeName: messageId
        KeyType: HASH
    GlobalSecondaryIndexes:
      - IndexName: roomIndex
        KeySchema:
          - AttributeName: room
            KeyType: HASH
        Projection:
          ProjectionType: ALL
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
      - IndexName: userIndex
        KeySchema:
          - AttributeName: userId
            KeyType: HASH
        Projection:
          ProjectionType: ALL
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
    ProvisionedThroughput:
      ReadCapacityUnits: 1
      WriteCapacityUnits: 1
    TableName: ${self:custom.tableName}

该表有一个简单的主键,然后是两个全局索引,每个索引都有一个简单的主键。

查询代码:

const params = {
    TableName: MESSAGES_TABLE,
    IndexName: "roomIndex",
    KeyConditionExpression: "room = :room",
    ExpressionAttributeValues: {
        ":room": { S: `${req.params.room}` }
    },
};
console.log(`QUERY ROOM ${JSON.stringify(params)}`);

dynamoDb.query(params, (error, result) => {
    if (error) {
        console.log(error);
        res.status(400).json({ error: 'Could not get messages' });
    } else {
        res.json(result.Items);
    }
});

【问题讨论】:

    标签: amazon-dynamodb serverless-framework dynamodb-queries aws-serverless


    【解决方案1】:

    我不得不承认有点尴尬。我在问题中多次表示我的代码没有使用 DocumentClient,而是使用了 DynamoDB 类。

    使用 DocumentClient,这个查询确实有效:

    {
        "TableName": "messages-table-dev",
        "IndexName": "roomIndex",
        "KeyConditionExpression": "room = :room",
        "ExpressionAttributeValues": {
            ":room": "everyone"
        }
    }
    

    这是因为 DocumentClient 不需要这些数据类型,而是推导出数据类型。

    事实证明,我的代码实际上是在使用 DocumentClient,一旦我从查询中删除数据类型,HTTP 请求就会按预期工作。而且,当转到 DynamoDB 客户端并添加回数据类型时,这也有效。

    如果我更仔细地查看应用程序代码,就永远不会发布这个问题。

    【讨论】:

      【解决方案2】:

      { "TableName": "messages-table-dev", "IndexName": "roomIndex", "KeyConditionExpression": "room = :room", "ExpressionAttributeValues": { ":room": "everyone" } }

      查询dynamoDb时无需输入数据类型

      【讨论】:

      • 如果我使用的是 DocumentClient,您所说的是准确的。就我而言,我一直在使用 DocumentClient,但忘记了代码正在使用 DocumentClient。从 DocumentClient 切换到 DynamoDB 后,我的代码就开始工作了。脸红。
      猜你喜欢
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 2015-11-05
      • 1970-01-01
      相关资源
      最近更新 更多