pythonamazon-dynamodbamazon-dynamodb-indexamazon-dynamodb-localpynamodb

PynamoDB Error for Local Secondary Index: ValueError('Table table_4 has no index: key1_index',)


I am new to pynamodb and I'm trying to query on LSI (already defined in dynamodb main table) and getting the following Exception.

'exception': ValueError('Table table_4 has no index: key1_index',)

UseCase: i wanted to query on LSI on hash_key only, as I have provided default value for key1 (range_key) and wanted to fetch the sorted data on the basis of key1.

LSI Model

class LSI_Index(LocalSecondaryIndex):
    id = UnicodeAttribute(hash_key=True)
    key1 = NumberAttribute(default=int(time.time()), range_key=True)

    class Meta:
        index = "key1-Index"
        projection = IncludeProjection(['id', 'key1', 'key2'])

Main Table Model

class MainModel(Model):
    id = UnicodeAttribute(hash_key=True)
    key2 = UnicodeAttribute(range_key=True, default='')
    key1 = NumberAttribute(default=int(time.time()))
    key1_index = LSI_Index()   # LSI

    class Meta:
        .....

Repository Method Code

    def read_by_LSI(cls, id):
    try:
        data = []
        iterator = MainModel.key1_index.query(hash_key=id,limit=1,scan_index_forward=False, consistent_read=True)
        for item in iterator:
            data.append(json.loads(json_dumps(item)))
        return data

DynamoDB Main Table Description:

{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "id",
                "AttributeType": "S"
            },
            {
                "AttributeName": "key1",
                "AttributeType": "N"
            }
        ],
        "TableName": "table_4",
        "KeySchema": [
            {
                "AttributeName": "id",
                "KeyType": "HASH"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": 1647447620.911,
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": 0.0,
            "LastDecreaseDateTime": 0.0,
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 10,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 779,
        "ItemCount": 7,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/table_4",
        "LocalSecondaryIndexes": [
            {
                "IndexName": "key1-Index",
                "KeySchema": [
                    {
                        "AttributeName": "id",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "key1",
                        "KeyType": "RANGE"
                    }
                ],
                "Projection": {
                    "ProjectionType": "INCLUDE",
                    "NonKeyAttributes": [
                        "key2",
                        "key1",
                    ]
                },
                "IndexSizeBytes": 779,
                "ItemCount": 7,
                "IndexArn": "arn:aws:dynamodb:ddblocal:000000000000:table/table_4/index/key1-Index"
            }
        ]
   }
}

Please tell me where I am doing wrong as I am not able to debug the issue. Thanks in advance.!!


Solution

  • So basically, when defining LSI Model in pynamodb, please make sure the Meta class attribute names are the same as mentioned in the doc - https://pynamodb.readthedocs.io/en/latest/indexes.html

    In the above instance, I did the following mistake due to which I was getting ValueError('table table_4 doesn't have key1_index') Exception.

    In MetaClass of LSI_Model Class, I used the wrong attribute name 'index' instead of 'index_name'. I have updated the code and now it works fine.

    class LSI_Index(LocalSecondaryIndex):
    id = UnicodeAttribute(hash_key=True)
    key1 = NumberAttribute(default=int(time.time()), range_key=True)
    
    class Meta:
        index_name = "key1-Index"
        projection = IncludeProjection(['id', 'key1', 'key2'])
    

    Note: LSI Meta Class attributes should be named as follows (mentioned in doc):

    1. index_name
    2. projection and so on..