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

Boolean values can be stored and fetched if the field type is `str` and not `bool` using `aredis`.

Open wiseaidev opened this issue 1 year ago • 4 comments

Hey everyone, I am trying to store and fetch in a model whose field's type is boolean. However, as you may know, Redis will complain about that when trying to encode bool values. But, I found a workaround for this use case, take the following as an example using the sync version redis_om:

from typing import Optional

from redis_om import Field, HashModel, JsonModel, Migrator


class Author(HashModel):
    first_name: str = Field(index=True)
    last_name: str
    active: Optional[bool] = Field(index=True, default=False)


class Blog(JsonModel):
    title: str = Field(index=True, full_text_search=True)
    content: str
    author: Author


Migrator().run()


author = Author(
    first_name="Mahmoud",
    last_name="Harmouch",
).save()

blog = Blog(
    title="Redis",
    content="Redis is a blazingly fast k/v store!",
    author=author
)


blog.save()

print(blog.pk)

assert Blog.find(Blog.pk == blog.pk).all()) == blog

Running this above script will throw the following exception:

redis.exceptions.DataError: Invalid input of type: 'bool'. Convert to a bytes, string, int or float first.

However, if you are using the async version, storing and indexing will work if the type is str. So to make boolean values work in aredis_om, just replace str in place of bool:

class Author(HashModel):
    first_name: str = Field(index=True)
    last_name: str
    active: Optional[str] = Field(index=True, default=False)


class Blog(JsonModel):
    title: str
    content: str
    author: Author = Field(index=True)

And your endpoints call async functions like the following to create/fetch k/v:

async def get_blogs(author: Optional[Author] = None):
    if not author:
        return await Author.find().all()
    else:
        return await Author.find(Author.author == author).all()

async def create_author(request: Request):
    return await Author(first_name=request.first_name, last_name=request.last_name, active=request.active).save()
    # or simply: return await Author(**request).save() if request is a dict.

Just wanted to share in case someone might find it helpful.

wiseaidev avatar Aug 16 '22 22:08 wiseaidev

thanks for you sharing, it is very useful, and I filtered the data in the following way::

await Author.find(Author.active== 'False').all()

Brandon-lz avatar Aug 24 '22 08:08 Brandon-lz

Great find! @simonprickett this seems also like a documentation issue

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

@sav-norem, this isn't documentation issue. In #193 he said:

Hi there - boolean fields aren't yet supported for JSON or Hash, they'll likely appear in JSON first as boolean is a native type there vs a Redis Hash that understands strings, floats and ints.

llirrikk avatar Sep 11 '22 12:09 llirrikk

@llirrikk - Sure! I meant more like we can label this as a documentation issue since it provides documentation and isn't raising a new bug type of issue that needs a new PR to fix.

sav-norem avatar Sep 15 '22 15:09 sav-norem