使用apoc.do.when时变量item未定义的问题排查求助
问题描述
在使用Neo4j的apoc.do.when()过程中,出现错误:
Neo4jError: Failed to invoke procedure 'apoc.do.when': Caused by: org.neo4j.exceptions.SyntaxException: Variable 'item' not defined...
但condition参数中可正常访问item变量。item是从cart的JSON数组解码而来,已通过创建Item节点验证解码正常,但尝试将变量传入if/elseQuery时仍报错。
相关Cypher代码:
with apoc.convert.fromJsonMap($json) as order create (o:Order) set o = order with o, apoc.convert.fromJsonMap($request) as request merge (u:User {uid: o.customerId}) merge (s:Shop {uid: o.shopId}) create (u)-[rel:MADE_ORDER]->(o)<-[rel1:RECEIVED_ORDER]-(s) with o, u, s, request unwind o.cart as jsonItems with o, u, s, request, apoc.convert.fromJsonMap(jsonItems) as item CALL apoc.do.when( item.isPromotion = false, 'match (pr:Product {id: item.id}) set pr.soldQuantity = pr.soldQuantity + 1, pr.availableQuantity = pr.availableQuantity -1 create(u)-[:BOUGHT]->(pr)<-[:CONTAINS]-(o) ', 'match (p:Promotion {id: item.id}) set p.soldQuantity = pr.soldQuantity + 1, pr.availableQuantity = p.availableQuantity -1 create(u)-[:BOUGHT]->(p)<-[:CONTAINS]-(o)' ,{}) YIELD value return o as savedOrder
测试代码(创建Item节点可正常运行):
with apoc.convert.fromJsonMap($json) as order create (o:Order) set o = order with o, apoc.convert.fromJsonMap($request) as request merge (u:User {uid: o.customerId}) merge (s:Shop {uid: o.shopId}) create (u)-[rel:MADE_ORDER]->(o)<-[rel1:RECEIVED_ORDER]-(s) with o, u, s, request unwind o.cart as jsonItems with o, u, s, request, apoc.convert.fromJsonMap(jsonItems) as item create (i: Item) set i = item return o as savedOrder
问题分析与解决
变量未传入子查询
apoc.do.when()的ifQuery和elseQuery是独立的子查询,外部的item、u、o变量不会自动传入,必须通过第四个参数(参数映射)显式传递。你当前第四个参数传的是空对象{},导致子查询里找不到这些变量。elseQuery中的变量笔误
elseQuery里匹配的是p:Promotion,但更新时错误使用了ifQuery里的pr变量,应该统一用p来操作Promotion节点的属性。
修复后的代码:
with apoc.convert.fromJsonMap($json) as order create (o:Order) set o = order with o, apoc.convert.fromJsonMap($request) as request merge (u:User {uid: o.customerId}) merge (s:Shop {uid: o.shopId}) create (u)-[rel:MADE_ORDER]->(o)<-[rel1:RECEIVED_ORDER]-(s) with o, u, s, request unwind o.cart as jsonItems with o, u, s, request, apoc.convert.fromJsonMap(jsonItems) as item CALL apoc.do.when( item.isPromotion = false, 'match (pr:Product {id: $item.id}) set pr.soldQuantity = pr.soldQuantity + 1, pr.availableQuantity = pr.availableQuantity - 1 create($u)-[:BOUGHT]->(pr)<-[:CONTAINS]-($o) ', 'match (p:Promotion {id: $item.id}) set p.soldQuantity = p.soldQuantity + 1, p.availableQuantity = p.availableQuantity - 1 create($u)-[:BOUGHT]->(p)<-[:CONTAINS]-($o)' , {item: item, u: u, o: o}) YIELD value return o as savedOrder
关键修改点:
- 在
apoc.do.when()的第四个参数中,将外部变量item、u、o传入子查询,参数映射为{item: item, u: u, o: o} - 子查询中使用
$item、$u、$o来引用传入的参数 - 修正elseQuery中的变量错误,把
pr改为p,确保更新的是Promotion节点的属性
内容的提问来源于stack exchange,提问作者Vincenzo
相关产品推荐
相关产品推荐

