我正在尝试在Cypher中实现逻辑,根据特定条件(CASE
Statement),我会创建一些节点和关系;代码如下
MATCH (g:Game)-[:PLAYER]->(u:User)-[r1:AT]->(b1:Block)-[:NEXT]->(b2:Block)
WHERE g.game_id='G222' and u.email_id = 'xyz@example.com' and b1.block_id='16'
SET r1.status='Skipped', r1.enddate=20141225
WITH u, b2,b1, g, r1
SET b1.test = CASE b2.fork
WHEN 'y' THEN
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2 {fork:'fail'}) RETURN 1
ELSE
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2) RETURN 2
END
WITH u, g
MATCH (u)-[:TIME]->(h:Time)<-[:TIME]-(g)
SET h.after = 0
SET h.before = h.before + 1
在此查询中,merge
中有WHEN 'y' THEN
个语句,此查询会引发错误:
无效输入']':预期的空格或关系模式(第7行,第82列) “MERGE(你) - [r2:STAGE {startdate:20141225,enddate:'99999999',status:'InProgress'}] - &gt;(b2 {fork:'fail'})RETURN 1”
基本上我正在尝试创建一个基于属性的关系,即MERGE
语句中的CASE
,我尝试了不同的方法让它像返回一样工作,这样就可以返回一些价值等等,但迄今为止没有任何效果。
此查询可能存在什么问题?
答案 0 :(得分:16)
要进行条件写入操作,您需要使用FOREACH
技巧。使用CASE
可以返回一个元素数组或一个空元素数组。 FOREACH
遍历CASE
表达式,因此有条件地执行操作。如果您还需要ELSE
部分,则需要使用FOREACH
中的反向条件设置另一个CASE
。例如,而不是
WHEN 'y' THEN
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2 {fork:'fail'}) RETURN 1
ELSE
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2) RETURN 2
END
使用
FOREACH(ignoreMe IN CASE WHEN 'y' THEN [1] ELSE [] END |
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2 {fork:'fail'})
)
FOREACH(ignoreMe IN CASE WHEN NOT 'y' THEN [1] ELSE [] END |
MERGE (u)-[r2:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2)
)
另请参阅Mark's blog post。
答案 1 :(得分:2)
修正了以下问题
WITH u, b2,b1, g, r1, CASE WHEN (b1.fork='y' and b2.fork='success') or (b1.fork='n') or (b1.fork='success') THEN ['ok'] ELSE [] END as array1
FOREACH (el1 in array1 | MERGE (u)-[r2:STAGE {startdate:20141225, enddate:99999999, status:'InProgress'}]->(b2))
即。使用CASE WHEN创建一个虚拟数组,该数组在某种程度上具有与匹配计数匹配的虚拟元素,然后使用FOREACH迭代结果。
再次感谢Stefan的想法...
Deepesh
答案 2 :(得分:1)
APOC插件支持Conditional Cypher Execution,现在我们可以避免FOREACH
的解决方法。
例如,您可以执行以下操作:
MATCH (g:Game)-[:PLAYER]->(u:User)-[r1:AT]->(b1:Block)-[:NEXT]->(b2:Block)
WHERE g.game_id='G222' AND u.email_id = 'xyz@example.com' AND b1.block_id='16'
SET r1.status='Skipped', r1.enddate=20141225
WITH u, b2, g
CALL apoc.do.when(
b2.fork = 'y',
"MERGE (u)-[:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2 {fork:'fail'})",
"MERGE (u)-[:STAGE {startdate:20141225, enddate:'99999999', status:'InProgress'}]->(b2)",
{u: u, b2: b2}) YIELD value
WITH u, g
MATCH (u)-[:TIME]->(h:Time)<-[:TIME]-(g)
SET h.after = 0
SET h.before = h.before + 1
答案 3 :(得分:0)
尽管这个答案确实对我有帮助,但我发现语法很难理解。所以这就是为什么我写自己的答案。在这里,我阅读了 tsv 文件并生成了多种类型的边线。
LOAD CSV WITH HEADERS FROM 'file:///data.tsv' AS r FIELDTERMINATOR '\t'
WITH r.movie_id as movie_id, r.person_id as person_id, r.category as category
MATCH (p:Person {person_id:person_id})
MATCH (m:Movie {movie_id:movie_id})
FOREACH (_ IN CASE WHEN category='actress' THEN [1] ELSE [] END |
MERGE (p)-[:ACTRESS {}]->(m)
)
FOREACH (_ IN CASE WHEN category='director' THEN [1] ELSE [] END |
MERGE (p)-[:DIRECTOR {}]->(m)
)
FOREACH (_ IN CASE WHEN category='cinematographer' THEN [1] ELSE [] END |
MERGE (p)-[:CINEMATOGRAPHER {}]->(m)
)
FOREACH (_ IN CASE WHEN category='actor' THEN [1] ELSE [] END |
MERGE (p)-[:ACTOR {}]->(m)
)
这里_
是一个变量,根本不会在任何地方使用,而是cypher语法的必要条件。