【发布时间】:2014-11-25 22:01:59
【问题描述】:
我在 Neo4j 2.1.5 上遇到过这个问题。我有一个使用 Neo4j REST API 从 Node.js 发出的查询。此查询的重点是能够创建或更新给定节点并将其状态(包括标签和属性)设置为某个已知状态。 WITH 之前的 MATCH 和 REMOVE 子句是为了解决这样一个事实,即没有直接的方法可以删除所有节点的标签,也没有办法用给定的标签集更新节点的标签。您必须明确删除您不想要的标签并添加您想要的标签。并且没有办法删除 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 查询中删除节点的所有现有标签并使用 ON MATCH 子句设置新标签。问题是包含初始 MATCH 似乎混淆了 ON MATCH 与 ON CREATE 逻辑。
假设 Brian 节点已经存在,这个查询的结果应该显示 n.created = false 和 n.updated = true。但是,我得到相反的结果,n.created=true,n.updated=false。如果我删除初始 MATCH(和 WITH)子句并仅执行 MERGE 子句,则结果符合预期。所以不知何故,包含 MATCH 子句会导致 MERGE 子句认为 CREATE vs MATCH 正在发生。
我意识到这是 WITH 子句的一种奇怪用法,但它似乎确实可以解决操作标签的限制。 Cypher 认为它是有效的 Cypher。我假设这只是一个错误和边缘案例,但我想在报告之前获得其他人的见解和可能的替代方案。
我意识到我可以创建一个事务并将 MATCH 和 MERGE 作为该事务中的单独查询发出,但有一些原因在我正在编写的 API 的设计中不能很好地工作。
谢谢!
【问题讨论】:
-
试图理解这个查询,我认为有些东西丢失了,特别是为什么下面的 MERGE 中没有使用来自
WITH m的m?我假设mprops和cprops作为变量绑定传入?从您的设置和描述中,老实说,我无法说出您为什么将其作为一个查询而不是两个查询来执行。第二个查询似乎不依赖于第一个查询,但您指出第一个查询弄乱了第二个查询。哪些 API 设计问题会阻止您发出多个查询? -
此外,在您的示例中,只有在 MATCH 成功时才会执行 MERGE,因此这应该是一个等效查询: MATCH (m {name:'Brian'}) REMOVE m:l1: l2 SET m={mprops} 返回 m
-
我已经根据我之前的评论添加了答案。
-
我正在尝试添加创建或更新逻辑,作为我正在编写的 Cypher 的包装 API 的一部分。 createOrUpdate() 方法想要设置新节点的状态或更新现有节点的状态,包括标签。所以我需要一种方法来删除所有标签,以便 MERGE 可以用新标签替换它们。 MATCH 查询的唯一目的是删除标签。这就是为什么合并查询不对“m”绑定做任何事情的原因。我不知道只有在 MATCH 成功时才会执行 MERGE,所以这无论如何都行不通。
-
出于明显的性能原因,我不想发出多个查询(需要多个 REST 请求)。我不想使用 REST 事务端点包含多个查询,因为我的包装 API 提供了创建事务并在该事务中包含多个包装 API 查询的选项。如果 createOrUpdate() 方法本身创建一个事务,这将不起作用。这就是为什么我一直在努力寻找在单个 Cypher 查询中更新节点状态的方法。