Вторичный индекс запроса DynamoDB ValidationException: тип параметра условия не соответствует типу схемы - PullRequest
0 голосов
/ 05 июня 2018

Я разрабатываю сервис AWS с использованием Serverless Framework.Пока у него есть одна таблица и пара глобальных вторичных индексов.Я пытаюсь выполнить запрос к глобальному вторичному индексу.

Запрос:

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

Это дает исключение - при использовании клиента DynamoDB Node.js, а не 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 для String.Следовательно, это сравнение строк и должно быть в порядке.

Опять же - я не использую 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);
    }
});

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Я должен признать, что немного смущен.Я несколько раз отвечал на вопрос, что мой код не использует DocumentClient, а использует класс DynamoDB.

С DocumentClient этот запрос действительно работает:

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

Это потому, что DocumentClient делаетне требуются эти типы данных, и вместо этого он выводит типы данных.

Оказывается, что мой код фактически использовал DocumentClient, и как только я удалил тип данных из запроса, HTTP-запрос заработал, как и ожидалось.И при переходе к клиенту DynamoDB и добавлении обратно типов данных, это тоже сработало.

Если бы я более внимательно посмотрел на код приложения, этот вопрос никогда бы не был опубликован.

0 голосов
/ 05 июня 2018

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

Нет необходимости указывать тип данных при запросе к DynamoDB

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...