diff --git a/src/validator/LookupValidator.cpp b/src/validator/LookupValidator.cpp
index dea681875b846487387ad66858ebbf3003ee3737..8e138912f9a242b8bd0c0de0719b6be56f8effc7 100644
--- a/src/validator/LookupValidator.cpp
+++ b/src/validator/LookupValidator.cpp
@@ -358,7 +358,9 @@ Status LookupValidator::rewriteRelExpr(RelationalExpression* expr) {
 
     std::string prop = la->right()->value().getStr();
     // rewrite ConstantExpression
-    auto c = leftIsAE ? checkConstExpr(right, prop) : checkConstExpr(left, prop);
+    auto relExprType = expr->kind();
+    auto c = leftIsAE ? checkConstExpr(right, prop, relExprType, leftIsAE)
+                      : checkConstExpr(left, prop, relExprType, leftIsAE);
 
     if (!c.ok()) {
         return Status::SemanticError("expression error : %s", left->toString().c_str());
@@ -387,7 +389,10 @@ Status LookupValidator::rewriteRelExpr(RelationalExpression* expr) {
     return Status::OK();
 }
 
-StatusOr<Value> LookupValidator::checkConstExpr(Expression* expr, const std::string& prop) {
+StatusOr<Value> LookupValidator::checkConstExpr(Expression* expr,
+                                                const std::string& prop,
+                                                const Expression::Kind kind,
+                                                bool leftIsAE) {
     if (!evaluableExpr(expr)) {
         return Status::SemanticError("'%s' is not an evaluable expression.",
                                      expr->toString().c_str());
@@ -397,6 +402,28 @@ StatusOr<Value> LookupValidator::checkConstExpr(Expression* expr, const std::str
     auto type = schema->getFieldType(prop);
     QueryExpressionContext dummy(nullptr);
     auto v = Expression::eval(expr, dummy);
+    // TODO(Aiee) extract the type cast logic as a method if we decide to support more cross-type
+    // comparisons.
+
+    // Allow different numeric type to compare
+    if (graph::SchemaUtil::propTypeToValueType(type) == Value::Type::FLOAT && v.isInt()) {
+        return v.toFloat();
+    } else if (graph::SchemaUtil::propTypeToValueType(type) == Value::Type::INT && v.isFloat()) {
+        // col1 < 10.5 range: [min, 11), col1 < 10 range: [min, 10)
+        double f = v.getFloat();
+        int iCeil = ceil(f);
+        int iFloor = floor(f);
+        if ((leftIsAE && (kind == Expression::Kind::kRelGE || kind == Expression::Kind::kRelLT)) ||
+            (!leftIsAE && (kind == Expression::Kind::kRelGT || kind == Expression::Kind::kRelLE))) {
+            // edge case col1 >= 40.0, no need to round up
+            if (abs(f - iCeil) < kEpsilon) {
+                return iFloor;
+            }
+            return iCeil;
+        }
+        return iFloor;
+    }
+
     if (v.type() != SchemaUtil::propTypeToValueType(type)) {
         return Status::SemanticError("Column type error : %s", prop.c_str());
     }
diff --git a/src/validator/LookupValidator.h b/src/validator/LookupValidator.h
index 0699455327e21a6bc87b8c9e3530817ff2c11751..fd6ffa2ea50cf8f2ce17a5d13e67fc566190fff4 100644
--- a/src/validator/LookupValidator.h
+++ b/src/validator/LookupValidator.h
@@ -44,7 +44,10 @@ private:
 
     Status rewriteRelExpr(RelationalExpression* expr);
 
-    StatusOr<Value> checkConstExpr(Expression* expr, const std::string& prop);
+    StatusOr<Value> checkConstExpr(Expression* expr,
+                                   const std::string& prop,
+                                   const Expression::Kind kind,
+                                   bool leftIsAE);
 
     Status checkTSService();
 
diff --git a/tests/tck/features/lookup/ByIndex.feature b/tests/tck/features/lookup/ByIndex.feature
index a21d603aff59cc13d10f3c8271953c32e4699bcb..0c925d5042b96f7fb49463361f2e6aacc9cac7ca 100644
--- a/tests/tck/features/lookup/ByIndex.feature
+++ b/tests/tck/features/lookup/ByIndex.feature
@@ -1,7 +1,9 @@
 Feature: Lookup by index itself
 
   Background:
-    Given a graph with space named "nba"
+    Given an empty graph
+    And load "nba" csv data to a new space
+    And wait 3 seconds
 
   Scenario: [1] tag index
     When executing query:
@@ -438,3 +440,176 @@ Feature: Lookup by index itself
       LOOKUP ON serve WHERE serve.start_year == serve.end_year YIELD serve.start_year AS startYear
       """
     Then a SemanticError should be raised at runtime:
+
+  Scenario: [1] Compare INT and FLOAT during IndexScan
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age == 40 YIELD player.age AS Age
+      """
+    Then the result should be, in any order:
+      | VertexID        | Age |
+      | "Dirk Nowitzki" | 40  |
+      | "Kobe Bryant"   | 40  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age > 40 YIELD player.age AS Age
+      """
+    Then the result should be, in any order:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age >= 40.0 YIELD player.age AS Age
+      """
+    Then the result should be, in any order:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+      | "Dirk Nowitzki"   | 40  |
+      | "Kobe Bryant"     | 40  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age > 40.5 YIELD player.age AS Age
+      """
+    Then the result should be, in any order:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age >= 40.5 YIELD player.age AS Age
+      """
+    Then the result should be, in any order:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age < 40
+      YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10
+      """
+    Then the result should be, in order, with relax comparison:
+      | VertexID            | Age | Name                |
+      | "Tracy McGrady"     | 39  | "Tracy McGrady"     |
+      | "David West"        | 38  | "David West"        |
+      | "Paul Gasol"        | 38  | "Paul Gasol"        |
+      | "Yao Ming"          | 38  | "Yao Ming"          |
+      | "Dwyane Wade"       | 37  | "Dwyane Wade"       |
+      | "Amar'e Stoudemire" | 36  | "Amar'e Stoudemire" |
+      | "Boris Diaw"        | 36  | "Boris Diaw"        |
+      | "Tony Parker"       | 36  | "Tony Parker"       |
+      | "Carmelo Anthony"   | 34  | "Carmelo Anthony"   |
+      | "LeBron James"      | 34  | "LeBron James"      |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age <= 40
+      YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10
+      """
+    Then the result should be, in order, with relax comparison:
+      | VertexID            | Age | Name                |
+      | "Dirk Nowitzki"     | 40  | "Dirk Nowitzki"     |
+      | "Kobe Bryant"       | 40  | "Kobe Bryant"       |
+      | "Tracy McGrady"     | 39  | "Tracy McGrady"     |
+      | "David West"        | 38  | "David West"        |
+      | "Paul Gasol"        | 38  | "Paul Gasol"        |
+      | "Yao Ming"          | 38  | "Yao Ming"          |
+      | "Dwyane Wade"       | 37  | "Dwyane Wade"       |
+      | "Amar'e Stoudemire" | 36  | "Amar'e Stoudemire" |
+      | "Boris Diaw"        | 36  | "Boris Diaw"        |
+      | "Tony Parker"       | 36  | "Tony Parker"       |
+
+  Scenario: [2] Compare INT and FLOAT during IndexScan
+    Given having executed:
+      """
+      CREATE TAG weight (WEIGHT double)
+      """
+    And having executed:
+      """
+      CREATE TAG INDEX weight_index
+      ON weight(WEIGHT)
+      """
+    And wait 6 seconds
+    When executing query:
+      """
+      INSERT VERTEX weight(WEIGHT)
+      VALUES "Tim Duncan" : (70.5)
+      """
+    Then the execution should be successful
+    When executing query:
+      """
+      INSERT VERTEX weight(WEIGHT)
+      VALUES "Tony Parker" : (80.0)
+      """
+    Then the execution should be successful
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT > 70;
+      """
+    Then the result should be, in any order:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT > 70.4;
+      """
+    Then the result should be, in any order:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT >= 70.5;
+      """
+    Then the result should be, in any order:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    Then drop the used space
+
+# (TODO) Unsupported cases due to the lack of float precision
+# When executing query:
+# """
+# LOOKUP ON weight
+# WHERE weight.WEIGHT > 70.5;
+# """
+# Then the result should be, in any order:
+# | VertexID      |
+# | "Tony Parker" |
+# When executing query:
+# """
+# LOOKUP ON weight
+# WHERE weight.WEIGHT <= 80.0;
+# """
+# Then the result should be, in any order:
+# | VertexID      |
+# | "Tim Duncan"  |
+# | "Tony Parker" |
diff --git a/tests/tck/features/lookup/ByIndex.intVid.feature b/tests/tck/features/lookup/ByIndex.intVid.feature
index 701b98fcea7626f45c3fb5b64c2bf7d0bdc1711c..9555402c2f30eb9110c254cab3e01ed3c5a74d52 100644
--- a/tests/tck/features/lookup/ByIndex.intVid.feature
+++ b/tests/tck/features/lookup/ByIndex.intVid.feature
@@ -1,7 +1,9 @@
 Feature: Lookup by index itself in integer vid
 
   Background:
-    Given a graph with space named "nba_int_vid"
+    Given an empty graph
+    And load "nba_int_vid" csv data to a new space
+    And wait 3 seconds
 
   Scenario: [1] tag index
     When executing query:
@@ -438,3 +440,176 @@ Feature: Lookup by index itself in integer vid
       LOOKUP ON serve WHERE serve.start_year == serve.end_year YIELD serve.start_year AS startYear
       """
     Then a SemanticError should be raised at runtime:
+
+  Scenario: [1] Compare INT and FLOAT during IndexScan
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age == 40 YIELD player.age AS Age
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID        | Age |
+      | "Dirk Nowitzki" | 40  |
+      | "Kobe Bryant"   | 40  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age > 40 YIELD player.age AS Age
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age >= 40.0 YIELD player.age AS Age
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+      | "Dirk Nowitzki"   | 40  |
+      | "Kobe Bryant"     | 40  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age > 40.5 YIELD player.age AS Age
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age >= 40.5 YIELD player.age AS Age
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID          | Age |
+      | "Grant Hill"      | 46  |
+      | "Jason Kidd"      | 45  |
+      | "Manu Ginobili"   | 41  |
+      | "Ray Allen"       | 43  |
+      | "Shaquile O'Neal" | 47  |
+      | "Steve Nash"      | 45  |
+      | "Tim Duncan"      | 42  |
+      | "Vince Carter"    | 42  |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age < 40
+      YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10
+      """
+    Then the result should be, in order, with relax comparison, and the columns 0 should be hashed:
+      | VertexID            | Age | Name                |
+      | "Tracy McGrady"     | 39  | "Tracy McGrady"     |
+      | "David West"        | 38  | "David West"        |
+      | "Paul Gasol"        | 38  | "Paul Gasol"        |
+      | "Yao Ming"          | 38  | "Yao Ming"          |
+      | "Dwyane Wade"       | 37  | "Dwyane Wade"       |
+      | "Amar'e Stoudemire" | 36  | "Amar'e Stoudemire" |
+      | "Boris Diaw"        | 36  | "Boris Diaw"        |
+      | "Tony Parker"       | 36  | "Tony Parker"       |
+      | "Carmelo Anthony"   | 34  | "Carmelo Anthony"   |
+      | "LeBron James"      | 34  | "LeBron James"      |
+    When executing query:
+      """
+      LOOKUP ON player WHERE player.age <= 40
+      YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10
+      """
+    Then the result should be, in order, with relax comparison, and the columns 0 should be hashed:
+      | VertexID            | Age | Name                |
+      | "Dirk Nowitzki"     | 40  | "Dirk Nowitzki"     |
+      | "Kobe Bryant"       | 40  | "Kobe Bryant"       |
+      | "Tracy McGrady"     | 39  | "Tracy McGrady"     |
+      | "David West"        | 38  | "David West"        |
+      | "Paul Gasol"        | 38  | "Paul Gasol"        |
+      | "Yao Ming"          | 38  | "Yao Ming"          |
+      | "Dwyane Wade"       | 37  | "Dwyane Wade"       |
+      | "Amar'e Stoudemire" | 36  | "Amar'e Stoudemire" |
+      | "Boris Diaw"        | 36  | "Boris Diaw"        |
+      | "Tony Parker"       | 36  | "Tony Parker"       |
+
+  Scenario: [2] Compare INT and FLOAT during IndexScan
+    Given having executed:
+      """
+      CREATE TAG weight (WEIGHT double)
+      """
+    And having executed:
+      """
+      CREATE TAG INDEX weight_index
+      ON weight(WEIGHT)
+      """
+    And wait 6 seconds
+    When executing query:
+      """
+      INSERT VERTEX weight(WEIGHT)
+      VALUES hash("Tim Duncan") : (70.5)
+      """
+    Then the execution should be successful
+    When executing query:
+      """
+      INSERT VERTEX weight(WEIGHT)
+      VALUES hash("Tony Parker") : (80.0)
+      """
+    Then the execution should be successful
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT > 70;
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT > 70.4;
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    When executing query:
+      """
+      LOOKUP ON weight
+      WHERE weight.WEIGHT >= 70.5;
+      """
+    Then the result should be, in any order, and the columns 0 should be hashed:
+      | VertexID      |
+      | "Tim Duncan"  |
+      | "Tony Parker" |
+    Then drop the used space
+
+# (TODO) Unsupported cases due to the lack of float precision
+# When executing query:
+# """
+# LOOKUP ON weight
+# WHERE weight.WEIGHT > 70.5;
+# """
+# Then the result should be, in any order, and the columns 0 should be hashed:
+# | VertexID      |
+# | "Tony Parker" |
+# When executing query:
+# """
+# LOOKUP ON weight
+# WHERE weight.WEIGHT <= 80.0;
+# """
+# Then the result should be, in any order, and the columns 0 should be hashed:
+# | VertexID      |
+# | "Tim Duncan"  |
+# | "Tony Parker" |