Cypher中的IF/ELSE
语句的语法是否有任何更新?
我知道CASE
和FOREACH
的“黑客”,但它们读起来太难看了:)
我想用可选参数做一些事情,比如:
CASE WHEN exists($refs.client) THEN MATCH (cl:client {uuid: $refs.client}) END
...
// and later use it like
CASE WHEN exists(cl) THEN DELETE tcr MERGE (t)-[:references]->(cl) END
// and again in my return
RETURN {
client: CASE WHEN exists(cl) THEN {uuid: cl.uuid} ELSE NULL END,
}
我知道这在上下文中没有多大意义,但我基本上传入了一个refs对象,该对象可能包含参数,也可能不包含参数(或者参数存在且为空)
在我读到的某个地方,可能有一个关于如何在neo4j中处理" if /else“的更新,所以我真的只想查看一下,看看是否有人意识到有一个”更好“的方法来处理这样的情况。
目前,我只是在代码中处理所有的查询,并运行一些较小的查询,但它需要重复查找来创建和删除引用。我想把它全部移到一个更大的查询中,这样我就可以使用变量引用了。
再说一次,我知道我可以使用FOREACH...CASE
,但是当有很多像这样的小案例时,它会变得很麻烦。
目前的错误是
{ Error: Invalid input 'S': expected 'l/L' (line 7, column 9 (offset: 246))
" CASE true WHEN exists($refs.client) THEN MATCH (cl:client {uuid: $refs.client}) END"
^
我还知道,如果我正在回传一个已知值,但不能在其中执行MATCH
,则可以使用WITH...CASE
。
想要在查询顶部的CASE
中执行MATCH
的原因之一是,如果refs上的属性存在,但MATCH
不成功,则查询将失败。使用OPTIONAL MATCH
不能做到这一点。
编辑哦还有..。我正在检查使用MATCH (cl:client {uuid: $refs.client}) WHERE exists($refs.client)
,但我记得它不能正常工作。
编辑:我可以做MATCH...WHERE exists()
,但是如果我不能做MERGE WHERE exists()
,那就是徒劳的
编辑以供参考,以显示我为什么要询问IF/ELSE,这是我正在查看的查询。我已经从上面的例子中修改了它,这样它就不会出错。
MATCH (u:user {uuid: $uid})-[:allowed_to {read: true}]->(c:company {uuid: $cid})
MATCH (t:timesheet {uuid: $tid})<-[:owns]-(:timesheets)<-[:owns]-(u)
// Make sure the incoming references are valid or fail query
// Here, I'd like only do a match IF $refs.client exists and IS NOT NULL. If it is null or does not exist, I don't want the query to fail. OPTIONAL MATCH will not fail if the value is passed in is invalid but will simply return NULL. Which is why IF/ELSE (or CASE) would be helpful here.
MATCH (cl:client {uuid: $refs.client})
MATCH (ca:case {uuid: $refs.case})
MATCH (s:step {uuid: $refs.step})
MATCH (n:note {uuid: $refs.note})
// clone timesheet entry to a revision
CREATE (t)-[:assembled_with]->(r:revision)
SET r = t, r.created_at = $data.updated_at
WITH *
// Get the old references
MATCH (t)-[tcr:references]->(rc:client)
MATCH (t)-[tcar:references]->(rca:case)
MATCH (t)-[tsr:references]->(rs:step)
MATCH (t)-[tnr:references]->(rn:note)
// Copy old references to revision (won't create new relationships with NULL)
MERGE (r)-[:references]->(rc)
MERGE (r)-[:references]->(rca)
MERGE (r)-[:references]->(rs)
MERGE (r)-[:references]->(rn)
// Update the current timesheet with new data
SET t += $data
// If new references are incoming, delete the old ones and update for new ones
DELETE tcr
DELETE tcar
DELETE tsr
DELETE tnr
MERGE (t)-[:references]->(cl)
MERGE (t)-[:references]->(ca)
MERGE (t)-[:references]->(s)
MERGE (t)-[:references]->(n)
WITH *
// Get the new count of revisions
MATCH (t)-[:assembled_with]->(_r:revision)
RETURN {
uuid: t.uuid,
start: t.start,
end: t.end,
description: t.description,
client: CASE WHEN exists(cl.uuid) THEN {uuid: cl.uuid} ELSE NULL END,
case: CASE WHEN exists(ca.uuid) THEN {uuid: ca.uuid} ELSE NULL END,
step: CASE WHEN exists(s.uuid) THEN {uuid: s.uuid} ELSE NULL END,
note: CASE WHEN exists(n.uuid) THEN {uuid: n.uuid} ELSE NULL END,
revisions: count(_r)
}
发布于 2017-05-15 22:11:57
APOC Procedures刚刚更新了对conditional cypher execution的支持。您需要3.1.3.7或更高版本(如果使用Neo4j 3.1.x),或者3.2.0.3或更高版本(如果使用Neo4j 3.2.x)。
以下是您提到的一些案例的示例,使用了新的过程:
CALL apoc.when($refs.client IS NOT NULL,
"MATCH (cl:client {uuid: refs.client}) RETURN cl", '', {refs:$refs}) YIELD value
WITH value.cl as cl // which might be null...
...
...
CALL apoc.do.when(cl IS NOT NULL,
"DELETE tcr
MERGE (t)-[:references]->(cl)", '', {tcr:tcr, t:t, cl:cl}) YIELD value
...
...
RETURN {
client: cl {.uuid}, ...
}
在您的返回中,地图投影足以满足您的需求,如果cl
存在,您将获得一个具有uuid的对象,如果不存在,则client
将为null。
发布于 2021-01-28 07:27:37
老问题,但有一些新技巧来实现条件循环执行,特别是在Neo4j 4.1.x中引入的子查询。
这篇知识库文章涵盖了可用的选项,我们将在其他方法可用时随时更新这篇文章。
https://neo4j.com/developer/kb/conditional-cypher-execution/
请注意,我的旧答案中的APOC方法仍然有效,并包含在本文中。
https://stackoverflow.com/questions/43481472
复制