diff --git a/aredis_om/model/model.py b/aredis_om/model/model.py
index 46857106..4bc2f8c3 100644
--- a/aredis_om/model/model.py
+++ b/aredis_om/model/model.py
@@ -1210,6 +1210,8 @@ def to_string(s):
                     map(to_string, res[i + offset][1::2]),
                 )
             )
+            # restore null values
+            fields = {key: val if val not in ["0", "0.0"] else None for key, val in fields.items()}
             # $ means a json entry
             if fields.get("$"):
                 json_fields = json.loads(fields.pop("$"))
@@ -1344,6 +1346,8 @@ async def get(cls, pk: Any) -> "HashModel":
         if not document:
             raise NotFoundError
         try:
+            # restore none values
+            document = {key: val if val not in ["0", "0.0"] else None for key, val in document.items()}
             result = cls.parse_obj(document)
         except TypeError as e:
             log.warning(
@@ -1360,14 +1364,14 @@ async def get(cls, pk: Any) -> "HashModel":
     @no_type_check
     def _get_value(cls, *args, **kwargs) -> Any:
         """
-        Always send None as an empty string.
+        Always send None as a zero string: "0" to handle Optional int and float fields.
 
         TODO: We do this because redis-py's hset() method requires non-null
         values. Is there a better way?
         """
         val = super()._get_value(*args, **kwargs)
         if val is None:
-            return ""
+            return "0"
         return val
 
     @classmethod
diff --git a/tests/test_hash_model.py b/tests/test_hash_model.py
index 84a05086..20eab834 100644
--- a/tests/test_hash_model.py
+++ b/tests/test_hash_model.py
@@ -53,6 +53,8 @@ class Member(BaseHashModel):
         join_date: datetime.date
         age: int = Field(index=True, sortable=True)
         bio: str = Field(index=True, full_text_search=True)
+        height: Optional[int] = Field(index=True)
+        weight: Optional[float] = Field(index=True)
 
         class Meta:
             model_key_prefix = "member"