Ошибка запроса AWS DynamoDB DocumentClient - одно или несколько значений параметра были недопустимыми: тип параметра условия не соответствует типу схемы

У меня есть таблица AWS DynamoDb с именем AccountXX, в которой хранятся элементы со структурой 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 есть глобальный вторичный индекс с именем Account_email_hash_salt_gsi, который имеет адрес электронной почты ключа раздела и дополнительные атрибуты hash, salt и id.

Когда я запускаю следующую команду интерфейса командной строки AWS, я могу успешно запросить элемент в таблице:

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": "[email protected]"}}

Однако, когда я выполняю аналогичный вызов с использованием экземпляра 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, чтобы я мог успешно запросить таблицу?


person vvg    schedule 04.02.2021    source источник


Ответы (1)


Нашел и устранил проблему. Проблема заключалась не в запросе DynamoDB или конструкции параметров. Основная причина заключалась в том, что лямбда-выражение передало тело запроса POST и обработчик неправильно его обработал. В обработчике отсутствовал JSON.parse(event.body) и, следовательно, loginToken был строкой. Следовательно, loginToken.email был оценен как пустой, что привело к сбою запроса.

Кстати, я нашел инструмент Amazon NoSQL Workbench, о котором упоминалось в ответ на другой аналогичный вопрос, который будет очень полезен при изучении запросов и их автогенерации с помощью пользовательского интерфейса. Я использовал это, чтобы убедиться, что параметры запроса были синтаксически правильными, а затем смог найти основную причину после некоторого устранения неполадок.

person vvg    schedule 04.02.2021