2

Serverless Framework を使用して AWS サービスを開発しています。これまでのところ、1 つのテーブルと 2 つのグローバル セカンダリ インデックスがあります。グローバル セカンダリ インデックスに対してクエリを実行しようとしています。

クエリ:

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

Node.js DocumentClient ではなく、Node.js DynamoDB クライアントを使用すると、例外が発生します。

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.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}

テーブルには単純な主キーがあり、それぞれが単純な主キーを持つ 2 つのグローバル インデックスがあります。

クエリ コード:

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);
    }
});
4

2 に答える 2

4

少し恥ずかしいことを認めなければなりません。私のコードは DocumentClient を使用しておらず、DynamoDB クラスを使用していると質問で何度か言いました。

DocumentClient を使用すると、このクエリは実際に機能します。

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

これは、DocumentClient がこれらのデータ型を必要とせず、代わりにデータ型を推測するためです。

私のコードは実際に DocumentClient を使用しており、クエリからデータ型を削除するとすぐに、HTTP 要求が期待どおりに機能したことがわかりました。また、DynamoDB クライアントに移動してデータ型を追加し直すと、これも機能しました。

アプリケーション コードをもっと注意深く見ていれば、この質問は投稿されなかったでしょう。

于 2018-06-05T21:36:17.443 に答える