Neo4j 将 ( / ) 除以零 ( 0 )

Neo4j Divide ( / ) by Zero ( 0 )

我在neo4j中查询

MATCH (n)-[t:x{x:"1a"}]->()
WHERE n.a > 1 OR n.b > 1 AND toFloat(n.a) / (n.a+n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC
LIMIT 10

但是我遇到了 / by zero 错误。

因为我声明 n.a 或 n.b 之一应该是 1,如果两者都为零,它应该跳过该行,我不应该得到这个错误。这看起来像是 Neo4j 中的逻辑问题。当我从 WHERE 子句中删除 AND toFloat(n.a)/(n.a+n.b)*100 < 90 时没有问题。但我希望结果只低于 90。我该如何克服这个问题?

n.an.b 都可以为负数吗?我能够通过以下方式重现此内容:

WITH -2 AS na, 2 AS nb
WHERE (na > 1 OR nb > 1) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb

我得到:/ by zero

也许尝试将 WHERE 子句更改为:

WITH -2 AS na, 2 AS nb
WHERE (na + nb > 0) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb

我得到:零行。

似乎第二个条件 toFloat(na) / (na + nb) * 100 < 90 在第一个条件之前进行了测试。看这个执行计划中的Filter(1)运算符:

+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     Operator | EstimatedRows | Rows | DbHits |                                            Identifiers |                                                                                                                                                                                      Other |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|   Projection |             1 |    3 |      0 | anon[111], anon[138], n, toFloat(n.a)/(n.a + n.b)* 100 |                                                                                                                                                                       anon[111]; anon[138] |
|          Top |             1 |    3 |      0 |                                   anon[111], anon[138] |                                                                                                                                                                             {  AUTOINT6};  |
|     Distinct |             0 |    3 |     24 |                                   anon[111], anon[138] |                                                                                                                                                                       anon[111], anon[138] |
|    Filter(0) |             0 |    3 |      6 |                                         anon[29], n, t |                                                                                                                                                                     t.x == {  AUTOSTRING0} |
|  Expand(All) |             1 |    3 |      6 |                                         anon[29], n, t |                                                                                                                                                                          (  n@7)-[t:x]->() |
|    Filter(1) |             1 |    3 |     34 |                                                      n | (Ors(List(n@7.a > {  AUTOINT1}, Multiply(Divide(ToFloatFunction(  n@7.a),Add(  n@7.a,  n@7.b)),{  AUTOINT3}) < {  AUTOINT4})) AND Ors(List(  n@7.a > {  AUTOINT1},   n.b > {  AUTOINT2}))) |
| AllNodesScan |             4 |    4 |      5 |                                                      n |                                                                                                                                                                                            |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

您可以通过强制将过滤器分成两个子句来解决这个问题。

MATCH (n)-[t:x { x:"1a" }]->()
WHERE n.a > 1 OR n.b > 1
WITH n
WHERE toFloat(n.a) / (n.a + n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC 
LIMIT 10

我发现这种行为令人惊讶,但当我想到它时,我认为执行引擎以这种方式重新排列过滤器并没有错。可能假设条件会在第一个声明的条件失败时提前放弃,但 Cypher 正是这样:声明性的。所以我们表达的是"what",而不是"how",在"what"方面,A and B等价于B and A

这是查询和示例图,您可以检查它是否转换为您的实际数据:
http://console.neo4j.org/r/f6kxi5