Neo4j Cypher query可选匹配多个CASE WHEN THEN

wfsdck30  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(131)

该场景是使用多个可选匹配项获取匹配节点的值之和,然后根据匹配情况选择值

MATCH (a:Type1 {id: '1234'})-[:REL_W]->(parentNode:Type2)
OPTIONAL MATCH (parentNode)<-[:REL_P]-(:Type2:Type3)-[:REL_W]->(qnode:Type1)
WITH qnode AS qwt
OPTIONAL MATCH (parentNode)<-[:REL_P]-(:Type2:Type4)-[:REL_I]-(:Type2)<-[:REL_W]-(lnode:Type1)
WITH qwt, lnode AS lwt
WITH qwt, lwt,
     CASE
         WHEN qwt IS NOT NULL AND 'Static' IN labels(qwt)
         THEN toFloat(qwt.value)
         WHEN lwt IS NOT NULL AND 'Static' IN labels(lwt)
         THEN toFloat(lwt.value)
         ELSE 0
     END AS childWeight
RETURN sum(childWeight) AS weight;

这段代码的问题是第二个CASE总是不执行。可选的匹配是重新调整qwt和lwt节点,然后数据也是正确的。如果我们将'lwt' case作为第一个case,那么它将执行,但'qwt' case将不会执行。

tsm1rwdh

tsm1rwdh1#

你的代码有几个问题。以下是一些主要的:
1.第一个WITH没有指定parentNode,所以第二个OPTIONAL MATCH必须找到所有可能的匹配节点,而不是重用前面找到的parentNode。这显然不利于您的结果,并会减慢查询速度。
1.每个MATCH子句(无论是否为OPTIONAL)都将导致工作行数的倍增,除非您采取措施防止这种情况(例如在MATCH子句之间进行聚合)。例如,如果您已经有5行,而MATCH生成10个结果,那么您最终将得到50行。这显然会大大扭曲最终的总和。
下面是一个应该更好地工作的查询(它还解决了其他一些效率低下的问题):

MATCH (:Type1 {id: '1234'})-[:REL_W]->(:Type2)<-[:REL_P]-(t2:Type2)
CALL {
  WITH t2
  MATCH (t2:Type3)-[:REL_W]->(qnode:Type1:Static)
  RETURN SUM(TOFLOAT(qnode.value)) AS qSum
}
CALL {
  WITH t2
  MATCH (t2:Type4)-[:REL_I]-(:Type2)<-[:REL_W]-(lnode:Type1:Static)
  RETURN SUM(TOFLOAT(lnode.value)) AS lSum
}
RETURN qSum + lSum AS weight

此外,您应该考虑将存储的value属性更改为浮点(而不是我假设的字符串)。这将允许您删除TOFLOAT s并加快查询速度。

相关问题