1

i'm using serverless framework with dynamodb [in Local]. trying to query with secondary indexed fields. goal is to query with few keys like we do in basic find queries in Mongo: {url:'<Somevalue>'} or may be like this {url:<somevalue>,ha:<somevalue>}

Table config i'm using currently:

serverless.yml

resources:
  Resources:
    TableName:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        TableName: ${file(./serverless.js):Tables.TableName.name}
        BillingMode: PAY_PER_REQUEST
        AttributeDefinitions:
          - AttributeName: 'id'
            AttributeType: 'S'
          - AttributeName: 'url'
            AttributeType: 'S'
          - AttributeName: 'ha'
            AttributeType: 'S'
          - AttributeName: 'GSI_1_PK'
            AttributeType: 'S'
          - AttributeName: 'GSI_1_SK'
            AttributeType: 'S'
        KeySchema:
          - AttributeName: 'id'
            KeyType: 'HASH'
        GlobalSecondaryIndexes:
          - IndexName: 'GSI_1'
            KeySchema:
              - AttributeName: 'GSI_1_PK'
                KeyType: 'HASH'
              - AttributeName: 'GSI_1_SK'
                KeyType: 'RANGE'
            Projection:
              ProjectionType: 'ALL'
          - IndexName: 'URI_1'
            KeySchema:
              - AttributeName: 'url'
                KeyType: 'HASH'
            Projection:
              ProjectionType: 'ALL'
          - IndexName: 'HASH_1'
            KeySchema:
              - AttributeName: 'ha'
                KeyType: 'HASH'
            Projection:
              ProjectionType: 'ALL'

  Outputs:
    TableNameARN:
      Value: { 'Fn::GetAtt': [TableName, Arn] }
      Export:
        Name: ${file(./serverless.js):Exports.TableNameARN}

with this, currently i'm only able to search with id field,

Q:

1> What are the changes needs to be made to query with different fields ? [which is secondary indexed , without using id in the query]

2> How do i search with multiple attributes? [i.e : {url:<somevalue>,ha:<somevalue>}]

Query i'm using :

var params = {
    TableName: '<TableName>',
    IndexName:'URI_1',
    Key: {
      url: 'http://something.com'
    }
};
docClient.get(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response
});

Output of the query:

{
message:"One of the required keys was not given a value",
code:"ValidationException,
...
}
0

1 Answer 1

3
  • You already used GSI which allows you to use secondary indexes. But you shoud use query instead of get, it allows you to query any table or secondary index that has a composite primary key (a partition key and a sort key).
  • Just use FilterExpression and ExpressionAttributeValues, it supports u to use multiple conditions.

var params = {
    TableName: '<TableName>',
    IndexName : 'URI_1',
    KeyConditionExpression : 'url = :url',
    FilterExpression : 'ha = :ha',
    ExpressionAttributeValues : {
      ':url': 'http://something.com',
      ':ha': 'aaaa'
    }
};
docClient.query(params, function(err, data) {
    if (err) console.log(err); // an error occurred
    else console.log(data); // successful response
});

additional

There're three Expressions we could use to query conditions, the first two of them are used for Dynamodb.query and the last one is used for Dynamodb.updateItem or Dynamodb.putItem:

  • KeyConditionExpression - where you need to specify partition key - required - or sort key in. It can only support table key by default, if you want to use Indexes like GSI, you should use it with IndexName.
  • FilterExpression - is applied after a Query finishes, but before the results are returned and FilterExpression cannot contain partition key or sort key attributes.
  • ConditionExpression - A condition that must be satisfied in order for a conditional update to succeed.
Sign up to request clarification or add additional context in comments.

7 Comments

got the point, but what if i have only the url and finding all doc which is having this url?
i'm getting error with ConditionExpression so i have used KeyConditionExpression , but with this encountered this error: Query condition missed key schema element , i'm guessing thats because not passing primary key.
It works in my case. I haven't found the failed reason yet, it is sure that you already used GSI which allows you to use secondary indexes without Primary Key
BTW, what's your DynamoDB API version?
i guess 2012-08-10 , anyways this is working only when i pass url but if i pass :ha too as its in the answer right now, its throwing error Query key condition not supported
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.