Cypher Neo4J - 使用MERGE进行CASE表达

时间:2014-12-20 02:36:24

标签: merge neo4j logic case cypher

我正在尝试在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,我尝试了不同的方法让它像返回一样工作,这样就可以返回一些价值等等,但迄今为止没有任何效果。

此查询可能存在什么问题?

4 个答案:

答案 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语法的必要条件。