Cypher Neo4J - 使用 MERGE 的 CASE 表达式
Posted
技术标签:
【中文标题】Cypher Neo4J - 使用 MERGE 的 CASE 表达式【英文标题】:Cypher Neo4J - CASE Expression with MERGE 【发布时间】:2015-02-19 00:03:06 【问题描述】:我正在尝试在 Cypher 中实现逻辑,根据特定条件(CASE
语句),我将创建一些节点和关系;代码如下
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
在这个查询中,WHEN 'y' THEN
中有一个merge
语句,这个查询抛出一个错误:
无效的输入“]”:预期的空白或关系模式(第 7 行,第 82 列) "合并 (u)-[r2:STAGE startdate:20141225, enddate:'99999999', status:'InProgress']->(b2 fork:'fail') 返回 1"
基本上,我正在尝试基于属性(即CASE
语句中的MERGE
)创建关系,我尝试了不同的方法来使其正常工作,例如返回,以便在返回某些值等情况下进行。到目前为止没有任何效果。
这个查询可能有什么问题?
【问题讨论】:
【参考方案1】:要执行条件写入操作,您需要使用FOREACH
技巧。使用 CASE
您可以返回一个元素数组或一个空数组。 FOREACH
迭代 CASE
表达式,因此有条件地执行操作。如果您还想要一个ELSE
部分,则需要使用CASE
中的逆条件来创建另一个FOREACH
。例如,而不是
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。
【讨论】:
谢谢Stefan,是的,你是对的,看来我们需要使用FOREACH,我还参考了你之前在***中的一篇文章,逻辑最终是这样的 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)) 好戏,但你能解释一下THEN [1] ELSE []
是什么意思,ignoreMe
是什么意思(对不起,我不能忽略你)?跨度>
Cypher 没有更新让我们忘记这个黑客?我真的很想知道,这个回复在 2018 年已经过时了。
@HerrIvan 这仍然是有条件合并的唯一方法吗?
@bigmadwolf:是的。这是我一年前的问题。但从那以后就没有答案了……也许 Stefan Armbruster 知道得更清楚。【参考方案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 的创意...
深度学习
【讨论】:
不把长长的业务逻辑放到CQL里面会更整洁。【参考方案3】: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
【讨论】:
【参考方案4】:虽然这个答案对我有帮助,但我发现语法很难理解。所以这就是我写自己的答案的原因。在这里,我读取了一个 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 Neo4J - 使用 MERGE 的 CASE 表达式的主要内容,如果未能解决你的问题,请参考以下文章