在单个Cypher查询中MERGE之前的MATCH混淆ON MATCH和ON CREATE

时间:2014-11-25 22:01:59

标签: neo4j cypher

我在Neo4j 2.1.5上碰到了这个问题。我有一个查询,我使用Neo4j REST API从Node.js发出。此查询的要点是能够创建或更新给定节点并将其状态(包括标签和属性)设置为某个已知状态。 WITH之前的MATCH和REMOVE子句是为了解决这样一个事实:没有直接的方法来删除所有Node标签,也没有办法更新Node的标签一组给定的标签。您必须明确删除您不想要的标签,并添加您想要的标签。并且没有办法删除MERGE子句中的标签。

查询的某种简化版本如下所示:

MATCH (m {name:'Brian'}) 
REMOVE m:l1:l2 
WITH m 
MERGE (n {name:'Brian'}) 
ON MATCH SET n={mprops} ON CREATE SET n={cprops} 
RETURN n

其中mprops = {updated:true, created:false}cprops = {updated:false, created:true}。我这样做是为了在单个Cypher查询中我可以删除所有Node的现有标签并使用ON MATCH子句设置新标签。问题是包括初始MATCH似乎混淆了ON MATCH和ON CREATE逻辑。

假设Brian Node已存在,此查询的结果应显示n.created = false和n.updated = true。但是,我得到相反的结果,n.created = true,n.updated = false。如果我删除了初始MATCH(和WITH)子句并仅执行MERGE子句,则结果与预期一致。因此,不知何故,包含MATCH子句会导致MERGE子句认为正在发生CREATE与MATCH。

我意识到这是对WITH子句的一种奇怪的用法,但它看起来似乎可以解决操纵标签的限制。 Cypher认为它是有效的Cypher。我假设这只是一个错误和一个边缘案例,但我想在报告之前获得其他人的见解和可能的替代方案。

我意识到我可以创建一个事务,并在该事务中将MATCH和MERGE作为单独的查询发布,但有理由说这在我编写的API的设计中不能很好地工作。

谢谢!

2 个答案:

答案 0 :(得分:3)

如果您使用MATCH为查询添加前缀,那么如果没有现有(' Brian')节点,它将永远不会执行。

您还应使用SET n = {param} SET n += {param}

覆盖所有属性
MERGE (n:Label { name:'Brian' })
ON MATCH  SET n += {create :false,update:true }
ON CREATE SET n += {create :true,update:false }
REMOVE n:WrongLabel
RETURN n

答案 1 :(得分:1)

我不明白为什么你的查询不起作用,但@FrobberOfBits带来的问题是有效的。

但是,从逻辑上讲,您的示例查询与此相同:

  MATCH (m {name:'Brian'}) 
  REMOVE m:l1:l2
  SET m={mprops}
  RETURN m

此查询更简单,完全避免使用MERGE,并且可以避免您看到的任何问题。这是否代表了你想要做的事情?