node.jsamazon-web-servicesamazon-dynamodbamazon-dynamodb-index

dynamodb query: ValidationException: The number of conditions on the keys is invalid


I have the following schema where I am basically just trying to have a table with id as primary key, and both code and secondCode to be global secondary indexes to use to query the table.

resource "aws_dynamodb_table" "myDb" {
  name         = "myTable"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "id"

  attribute {
    name = "id"
    type = "S"
  }

  attribute {
    name = "code"
    type = "S"
  }

  attribute {
    name = "secondCode"
    type = "S"
  }

  global_secondary_index {
    name = "code-index" 
    hash_key = "code"
    projection_type = "ALL"
  }

  global_secondary_index {
    name = "second_code-index" 
    hash_key = "secondCode"
    projection_type = "ALL"
  }
}

When I try to look for one item by code

const toGet = Object.assign(new Item(), {
    code: 'code_456',
});

item = await dataMapper.get<Item>(toGet);

locally I get

ValidationException: The number of conditions on the keys is invalid

and on the deployed instance of the DB I get

The provided key element does not match the schema

I can see from the logs that the key is not being populated

Serverless: [AWS dynamodb 400 0.082s 0 retries] getItem({ TableName: 'myTable', Key: {} })

Here is the class configuration for Item

@table(getEnv('MY_TABLE'))
export class Item {
    @hashKey({ type: 'String' })
    id: string;

    @attribute({
        indexKeyConfigurations: { 'code-index': 'HASH' },
        type: 'String',
    })
    code: string;

    @attribute({
        indexKeyConfigurations: { 'second_code-index': 'HASH' },
        type: 'String',
    })
    secondCode: string;

    @attribute({ memberType: embed(NestedItem) })
    nestedItems?: Array<NestedItem>;
}

class NestedItem {
    @attribute()
    name: string;
    @attribute()
    price: number;
}

I am using https://github.com/awslabs/dynamodb-data-mapper-js


Solution

  • I looked at the repo you linked for the package, I think you need to use the .query(...) method with the indexName parameter to tell DynamoDB you want to use that secondary index. Usuallly in DynamoDB, get operations use the default keys (in your case, you'd use get for queries on id, and query for queries on indices).

    Checking the docs, it's not very clear - if you look at the GetItem reference, you'll see there's nowhere to supply an index name to actually use the index, whereas the Query operation allows you to supply one. As for why you need to query this way, you can read this: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html