redis-om-python icon indicating copy to clipboard operation
redis-om-python copied to clipboard

JsonModel: find not working with timedelta

Open gam-phon opened this issue 2 years ago • 2 comments

Hello,

In JsonModel, find not working with timedelta, whereas HashModel is working

Check out below code:

class Customer(JsonModel):
    name: str = Field(title="Name", index=True)


class RestaurantVisit1(JsonModel):
    customer_pk: str = Field(index=True)
    registered_at: datetime.datetime = Field(title="Registered At")

# Not Working
class RestaurantVisit2(JsonModel):
    customer_pk: str = Field(index=True)
    registered_at: datetime.datetime = Field(title="Registered At")
    waiting_duration: datetime.timedelta = Field(title="Waiting Duration")


class RestaurantVisit3(HashModel):
    customer_pk: str = Field(index=True)
    registered_at: datetime.datetime = Field(title="Registered At")
    waiting_duration: datetime.timedelta = Field(title="Waiting Duration")

Migrator().run()

c = Customer(name="Brookins").save()
v1 = RestaurantVisit1(
    customer_pk=c.pk,
    registered_at=datetime.datetime.now(),
).save()
v2 = RestaurantVisit2(
    customer_pk=c.pk,
    registered_at=datetime.datetime.now(),
    waiting_duration=datetime.timedelta(minutes=15),
).save()
v3 = RestaurantVisit3(
    customer_pk=c.pk,
    registered_at=datetime.datetime.now(),
    waiting_duration=datetime.timedelta(minutes=15),
).save()

print("Customer Get: ", Customer.get(pk=c.pk))
print("Customer Find: ", Customer.find(Customer.name == "Brookins").all())
print("RestaurantVisit1 Get: ", RestaurantVisit1.get(pk=v1.pk))
print(
    "RestaurantVisit1 Find: ",
    RestaurantVisit1.find(RestaurantVisit1.customer_pk == c.pk).all(),
)
print("RestaurantVisit2 with datetime.timedelta Get: ", RestaurantVisit2.get(pk=v2.pk))
# Not Working
print(
    "RestaurantVisit2 with datetime.timedelta Find: ",
    RestaurantVisit2.find(RestaurantVisit2.customer_pk == c.pk).all(),
)
print(
    "RestaurantVisit3 with datetime.timedelta HashModel Get: ",
    RestaurantVisit3.get(pk=v3.pk),
)
print(
    "RestaurantVisit3 with datetime.timedelta HashModel Find: ",
    RestaurantVisit3.find(RestaurantVisit3.customer_pk == c.pk).all(),
)

Results:

Customer Get:  pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2' name='Brookins'
Customer Find:  [Customer(pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2', name='Brookins')]
RestaurantVisit1 Get:  pk='01FRAFY4KGGAYFG7JZ468417FG' customer_pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2' registered_at=datetime.datetime(2022, 1, 1, 12, 36, 7, 792310)
RestaurantVisit1 Find:  [RestaurantVisit1(pk='01FRAFY4KGGAYFG7JZ468417FG', customer_pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2', registered_at=datetime.datetime(2022, 1, 1, 12, 36, 7, 792310))]
RestaurantVisit2 with datetime.timedelta Get:  pk='01FRAFY4KKYTJE78EBQNBHP9KE' customer_pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2' registered_at=datetime.datetime(2022, 1, 1, 12, 36, 7, 795804) waiting_duration=datetime.timedelta(seconds=900)
RestaurantVisit2 with datetime.timedelta Find:  []
RestaurantVisit3 with datetime.timedelta HashModel Get:  pk='01FRAFY4KN7Y5YZ3TRGKEQNS8R' customer_pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2' registered_at=datetime.datetime(2022, 1, 1, 12, 36, 7, 797948) waiting_duration=datetime.timedelta(seconds=900)
RestaurantVisit3 with datetime.timedelta HashModel Find:  [RestaurantVisit3(pk='01FRAFY4KN7Y5YZ3TRGKEQNS8R', customer_pk='01FRAFY4KDH6Q0TRQ6CX7JJ6Z2', registered_at=datetime.datetime(2022, 1, 1, 12, 36, 7, 797948), waiting_duration=datetime.timedelta(seconds=900))]

gam-phon avatar Jan 01 '22 09:01 gam-phon

This will resolve it:

from pydantic.json import timedelta_isoformat

class RestaurantVisit2(JsonModel):
    customer_pk: str = Field(index=True)
    registered_at: datetime.datetime = Field(title="Registered At")
    waiting_duration: datetime.timedelta = Field(title="Waiting Duration")

    class Config:
        json_encoders = {
            datetime.timedelta: timedelta_isoformat,
        }

gam-phon avatar Jan 01 '22 10:01 gam-phon

Thanks for finding a way to make it work! @simonprickett - should we look into why timedelta isn't really supported or make a documentation issue with a workaround?

sav-norem avatar Aug 31 '22 13:08 sav-norem