stevearc / flywheel

Object mapper for Amazon's DynamoDB
MIT License
128 stars 25 forks source link

Query and return multiple records based on the hash key #65

Closed labeneator closed 5 years ago

labeneator commented 5 years ago

I seem to be having an issue in selection multiple conversation ids based on the model below


class Transaction(Model):
    conversation_id = Field(hash_key=True)
    msisdn = Field(range_key=True)
    timestamp = Field(type=datetime, index='timestamp-index')
    amount = Field(type=NUMBER)
    posted_timestamp = Field(type=datetime)
    transaction_time = Field(type=datetime)

So I constructed the following query

tx_ids = ['b501d92c-27e0-11e9-a206-06299faea7c2', '80a2107e-2147-11e9-a206-06299faea7c2']
txs = engine.query(
    Transaction
).filter(
    Transaction.conversation_id.in_(tx_ids)
).all()

Which errors out with

/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/flywheel/fields/conditions.py in query_kwargs(self, model)
     66 
     67         if ordering is None:
---> 68             raise ValueError("Bad query arguments. You must provide a hash "
     69                              "key and may optionally constrain on exactly one "
     70                              "range key")

ValueError: Bad query arguments. You must provide a hash key and may optionally constrain on exactly one range key

Which is odd. I thought I could provide multiple hash keys . A single one works as expected

tx_ids = ['b501d92c-27e0-11e9-a206-06299faea7c2', '80a2107e-2147-11e9-a206-06299faea7c2']
txs = engine.query(
    Transaction
).filter(
    Transaction == tx_ids[0]
).all()

An or_filter with multiple filters also doesn't work

tx_ids = ['b501d92c-27e0-11e9-a206-06299faea7c2', '80a2107e-2147-11e9-a206-06299faea7c2']
txs = engine.query(Transaction).filter(
    Transaction.conversation_id == tx_ids[0]
).filter(
    Transaction.conversation_id == tx_ids[1]
).all(filter_or=True)

print(len(txs))  # Returns 1 instead of 2
labeneator commented 5 years ago

I found a workaround using batch get. For future reference:

engine.get(B2CTransaction, [
    {
        'conversation_id':'b501d92c-27e0-11e9-a206-06299faea7c2',  
        'msisdn': '254712123456'
    },
        {
        'conversation_id':'80a2107e-2147-11e9-a206-06299faea7c2', 
        'msisdn': '254712123456'
    }
    ]
)