How to instantiate a class model with a Local Secondary Index using PynamoDB?

229 Views Asked by At

I need to instantiate a class model that uses a Local Secondary Index with the PynamoDB library, but I'm getting errors. My code:

class MyIndex(LocalSecondaryIndex):
    
    class Meta:
        projection = AllProjection()
    
    org_id = UnicodeAttribute(hash_key=True)
    user_id = UnicodeAttribute(range_key=True)


class MyModel(Model):
    
    class Meta:
        table_name = 'my-table'
        region = 'eu-west-1'
        aws_access_key_id = '...'
        aws_secret_access_key = '...'
    
    org_id = UnicodeAttribute(hash_key=True)
    doc_id = UnicodeAttribute(range_key=True)
    user_index = MyIndex()

    attr_one = NumberAttribute()
    attr_two = UnicodeAttribute()
    attr_three = NumberAttribute()

This is my first time using an index (either local or global) with PynamoDB. The docs don't actually give an example (that I have seen) of instantiating a model class using an index, just the model/index definitions and then examples of querying (I'm referring to the readthedocs here and the github examples here).

My first attempt to test this out looked like this:

MyModel(
    org_id = my_org_id,
    doc_id = my_doc_id,
    user_index = MyIndex(my_org_id, 'abc123'),
    attr_one = 1,
    attr_two = 'foo',
    attr_three = 3,
)

...but I got the following error on the MyIndex constructor:

TypeError: __init__() takes 1 positional argument but 3 were given

Removing the first parameter my_org_id gave me the error above with ...but 2 were given. I've also tried user_index = 'abc123' and user_id = 'abc123' but in both cases I get ValueError: Attribute user_* specified does not exist.

Could someone show me how this is supposed to work or point me in the direction of a working example please?

1

There are 1 best solutions below

0
On

I only just realized from the examples that the sort key being used in the LSI must also must specified as an attribute on the table using the LSI, so that got it working e.g.

class MyModel(Model):

    class Meta:
        table_name = 'my-table'
        region = 'eu-west-1'
        aws_access_key_id = '...'
        aws_secret_access_key = '...'

    org_id = UnicodeAttribute(hash_key=True)
    doc_id = UnicodeAttribute(range_key=True)
    user_index = MyIndex()
    user_id = UnicodeAttribute() ### this was missing