2

I have a table created with the serverless framework:

resources:
  Resources:
    withdawlRequestTable: 
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:provider.environment.WITHDRAWAL_REQUEST_TABLE}
        AttributeDefinitions:
          - AttributeName: pk
            AttributeType: S
          - AttributeName: sk
            AttributeType: S
        KeySchema:
          - AttributeName: pk
            KeyType: HASH
          - AttributeName: sk
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        GlobalSecondaryIndexes:
        - IndexName: sk-pk-index
          KeySchema:
          - AttributeName: sk
            KeyType: HASH
          - AttributeName: pk
            KeyType: RANGE
          Projection:
            ProjectionType: ALL
          ProvisionedThroughput: 
            ReadCapacityUnits: 1
            WriteCapacityUnits: 1

I am now trying to query that table with the begins_with operator but I keep getting this error:

INFO    ValidationException: Invalid KeyConditionExpression: Incorrect operand type for operator or function; operator or function: begins_with, operand type: M
    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) {
  code: 'ValidationException',
  time: 2021-04-02T19:51:30.009Z,
  requestId: 'NC1F1C5708U6ARMJKQ05IKJLE3VV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 14.409529163729463
}

Not sure what I am doing wrong as both pk is the partition key and sk is the sort key, I should be able to query using KeyConditionExpression but it not working.

here is my code in nodejs:

module.exports.get = async function(userId, withdrawlId) {
    const getParams = {
        TableName: tableName,
        KeyConditionExpression: 'pk = :userId AND begins_with(sk, :withdrawlId)',
        ExpressionAttributeValues: {
            ':userId': {'S': 'USER#' + userId},
            ':withdrawlId': {'S': withdrawlId}
        }
    }
    let getResult
    try {
        getResult = await dynamodb.query(getParams).promise()
        return getResult.Item
    } catch (error) {
        console.log(error)
        throw new Error(error)
    }
}
0xtuytuy
  • 1,494
  • 6
  • 26
  • 51

1 Answers1

5

When using the DocumentClient you don't specify the type in the ExpressionAttributeValues. So your code should look like this instead.

module.exports.get = async function(userId, withdrawlId) {
    const getParams = {
        TableName: tableName,
        KeyConditionExpression: '#pk = :userId AND begins_with(#sk, :withdrawlId)',
        ExpressionAttributeValues: {
            ':userId': 'USER#' + userId,
            ':withdrawlId': withdrawlId
        },
        ExpressionAttributeNames: {
            '#pk': 'pk',
            '#sk': 'sk'
        }
    }
    let getResult
    try {
        getResult = await dynamodb.query(getParams).promise()
        return getResult.Items
    } catch (error) {
        console.log(error)
        throw new Error(error)
    }
}

I tend to always favor using ExpressionAttributeNames to avoid potential reserved word clashes, but I don't believe you should have to do that in your case.

Notice also that the result has an Items property, not an Item property.

Jason Wadsworth
  • 8,059
  • 19
  • 32