Neo4j Cypher - 有条件的 With 子句查询

Posted

技术标签:

【中文标题】Neo4j Cypher - 有条件的 With 子句查询【英文标题】:Neo4j Cypher- Conditional With clause query 【发布时间】:2018-12-27 20:28:11 【问题描述】:

我正在编写以下 Neo4j Cypher 查询以添加新的 Part 并从 Vehicle 节点中删除旧的 Part。我正在使用 Neo4j(版本 3.4.1)

newPartsremovedParts 是我的参数。它们是String 的列表。

with newParts AS newParts
unwind newParts as newPart
match (r:Vehicle) where id(r)=639
merge (r)-[:HAS_PART]->(np:Partname:newPart)
on create np+=lastModifiedDateTime:localdatetime(), createdDateTime:localdatetime()
with r optional match (r)-[rel:HAS_PART]-(p:Part) where p.name in removedParts
delete rel
with r match q=(r)--()
return nodes(q), relationships(q))

当我提供 newParts 参数为非空时它工作正常。

但是,当它为空时,我无法取回最终的节点和关系。我确实理解为什么会发生这种情况,因为当列表为空时 unwind 会停止执行。我尝试将with..unwind 部分移动到del 下方,它成功删除了removedParts Part。 但是,它不会在展开后返回最终节点和关系。

我也不确定如何使用空的 newParts 参数来完成这项工作。我试图使用case,但我认为case 不适用于节点和关系。

任何帮助或指点将不胜感激。

提前致谢

V

【问题讨论】:

您是否尝试过使用case size(newParts) ... 【参考方案1】:

想法

您可以将APOC user library 的conditional cypher execution 与对参数newParts 的非空检查结合使用。请首选apoc.do.when 而不是apoc.when,因为它是在读/写上下文中执行的,这对于MERGE 子句是必需的。

建议的解决方案

WITH $newParts AS newParts, $removedParts AS removedParts
CALL apoc.do.when(
size($newParts) > 0,
// true case
'
  UNWIND newParts AS newPart
  MATCH (r:Vehicle) WHERE id(r)=639
  MERGE (r)-[:HAS_PART]->(np:Partname:newPart)
  ON CREATE np+=lastModifiedDateTime:localdatetime(), createdDateTime:localdatetime()
  RETURN r;
',
// false case
'
  UNWIND newParts AS newPart
  MATCH (r:Vehicle) WHERE id(r)=639
  RETURN r;
',
newParts: newParts) YIELD value AS result
WITH DISTINCT result.r AS r, removedParts
OPTIONAL MATCH (r)-[rel:HAS_PART]-(p:Part) WHERE p.name IN removedParts
DELETE rel
WITH DISTINCT r 
MATCH q=(r)--()
RETURN nodes(q), relationships(q);

说明

第 2 行:调用 APOC 用户库的 if-then-else 构造 第 3 行:要评估的条件,在这种情况下检查参数newParts 是否不为空 第 5-11 行:if 部分,移交 Vehicle r 第 13-17 行:else 部分 第 18 行:定义必须提供给 if-then-else 构造的参数并从中检索结果

【讨论】:

感谢@ThirstForKnowledge 的帮助。但是,运行查询时出现异常:SyntaxError: WITH is required between DELETE and MATCH (line 22, column1) 感谢您的反馈,我在DELETE 声明之后添加了一个符合WITH DISTINCT r 的内容。【参考方案2】:

感谢 Neo4j 管理员在 Neo4j slack 频道上的建议和建议,我能够为自己的问题找到答案。

如果您想使用普通的 Cypher 查询,您可以使用以下答案:

MATCH (r:Vehicle) WHERE id(r)=639
FOREACH(newPart IN newParts| 
MERGE (np:Partid:newPart)
ON CREATE SET np+=partProperties
MERGE (r)-[:HAS_PART]->(np))
WITH DISTINCT r SET r+=vehicleProperties 
WITH DISTINCT r OPTIONAL MATCH p=(r)-[rel:HAS_PART]-(p:Part) where p.name in removedParts 
DELETE rel 
WITH DISTINCT r 
MATCH q=(r)--() 
RETURN q

希望有人觉得它有帮助!

问候, V

【讨论】:

以上是关于Neo4j Cypher - 有条件的 With 子句查询的主要内容,如果未能解决你的问题,请参考以下文章

在 CREATE 和 MATCH 之间需要 Neo4j Cypher WITH

如何在neo4j Cypher中获取列表的子集

Neo4j Cypher 语言学习

Neo4j 第十一篇:Cypher函数

Cypher Neo4J - 使用 MERGE 的 CASE 表达式

Neo4j/Cypher 测试数据请求