PynamoDB icon indicating copy to clipboard operation
PynamoDB copied to clipboard

IndexMeta removal prevents index class reuse

Open giovannibelzoni opened this issue 1 year ago • 2 comments

https://github.com/pynamodb/PynamoDB/pull/998

This PR has made index class reuse impossible, due in part by the __set_name__ method on the index class setting the first model it's used on.

Prior to this change, it was possible to define an index class and use it on multiple models. Now we see:

In [2]: ModelA._indexes['MyIndex'].Meta.model
Out[2]: app.models.ModelA

In [3]: ModelB._indexes['MyIndex'].Meta.model
Out[3]: app.models.ModelA

I suspect this is the problem for this reported bug: https://github.com/pynamodb/PynamoDB/issues/1026

giovannibelzoni avatar Jul 13 '23 01:07 giovannibelzoni

We could allow reuse since an index should only be useable as an instance on a model, i.e. MyIndex.query(...) should no longer be possible in the current version.

ikonst avatar Jul 13 '23 03:07 ikonst

I see this bug in version 5.5.1.

There are two workarounds I know of:

  • Mentioned elsewhere is to not use the index for querying, but instead pass index_name to the regular query() function.
class CommonIndex(GlobalSecondaryIndex):
    ...
    
class ModelA:
    the_index = CommonIndex()

class ModelB:
    the_index = CommonIndex()
    
ModelB.query(key, index_name='the_index'...) # works as expected
ModelB.the_index.query(key, ...) # queries ModelA!!
  • Define and instantiate new classes for every "common" index instance (this is a bit ugly, but avoids people having to remember to use query(...index_name=""...)
def CommonIndex -> GlobalSecondaryIndex:
    class InnerCommonIndex(GlobalSecondaryIndex):
         ...
    return InnerCommonIndex()
     
 class ModelA:
     the_index = CommonIndex()

 class ModelB:
     the_index = CommonIndex()

ModelB.the_index.query(key, ...) # works as expected

andrewdodd avatar Aug 05 '24 12:08 andrewdodd