如果...与Cypher Neo4J一起使用

时间:2017-04-18 20:19:06

标签: neo4j cypher

Cypher中IF/ELSE语句的语法是否有任何更新?

我知道CASEFOREACH" hacks"但是它们看起来很难看。)

我想用可选参数做一些事情,例如:

CASE WHEN exists($refs.client) THEN MATCH (cl:client {uuid: $refs.client}) END
...

// and later use it like
CASE WHEN exists(cl) THEN DELETE tcr MERGE (t)-[:references]->(cl) END

// and again in my return
RETURN {
  client: CASE WHEN exists(cl) THEN {uuid: cl.uuid} ELSE NULL END,
}

我知道在给定上下文的情况下并没有多大意义,但我基本上传入的refs对象可能包含也可能不包含参数(或者参数存在且为NULL)

我读到的地方可能会更新" if / else"可能会在neo4j处理,所以我真的只是想检查一下,看看是否有人知道"更好的"处理这种情况的方法。

目前,我只是在代码中处理所有查询并运行一堆较小的查询,但它需要重复查找才能创建和删除引用。我想将它全部移动到一个更大的查询中,以便我可以使用变量引用。

同样,我知道我可以使用FOREACH...CASE,但是当有很多像这样的小案例时,它会变得毛茸茸。

目前错误是

{ Error: Invalid input 'S': expected 'l/L' (line 7, column 9 (offset: 246))
"      CASE true WHEN exists($refs.client) THEN MATCH (cl:client {uuid: $refs.client}) END"
         ^

我也知道,如果我传回一个已知值,我可以使用WITH...CASE,但不能在其中执行MATCH

想要在查询顶部的MATCH内进行CASE的原因之一是因为如果refs上的属性存在但MATCH我希望查询失败}没有成功。使用OPTIONAL MATCH无法实现此目的。

EDIT 哦,也......我正在审查使用 MATCH (cl:client {uuid: $refs.client}) WHERE exists($refs.client)但我记得不能正常工作。

EDIT 我可以做MATCH...WHERE exists()但后来如果我不能做MERGE WHERE exists()

那就没有用了

EDIT 为了参考以显示我询问IF / ELSE的原因,这里是我正在查看的查询。我已经从上面的示例修改了它,因此它不会出错。

MATCH (u:user {uuid: $uid})-[:allowed_to {read: true}]->(c:company {uuid: $cid})
MATCH (t:timesheet {uuid: $tid})<-[:owns]-(:timesheets)<-[:owns]-(u)

// Make sure the incoming references are valid or fail query
// Here, I'd like only do a match IF $refs.client exists and IS NOT NULL. If it is null or does not exist, I don't want the query to fail. OPTIONAL MATCH will not fail if the value is passed in is invalid but will simply return NULL. Which is why IF/ELSE (or CASE) would be helpful here.
MATCH (cl:client {uuid: $refs.client})
MATCH (ca:case {uuid: $refs.case})
MATCH (s:step {uuid: $refs.step})
MATCH (n:note {uuid: $refs.note})

// clone timesheet entry to a revision
CREATE (t)-[:assembled_with]->(r:revision)
SET r = t, r.created_at = $data.updated_at

WITH *

// Get the old references
MATCH (t)-[tcr:references]->(rc:client)
MATCH (t)-[tcar:references]->(rca:case)
MATCH (t)-[tsr:references]->(rs:step)
MATCH (t)-[tnr:references]->(rn:note)

// Copy old references to revision (won't create new relationships with NULL)
MERGE (r)-[:references]->(rc)
MERGE (r)-[:references]->(rca)
MERGE (r)-[:references]->(rs)
MERGE (r)-[:references]->(rn)

// Update the current timesheet with new data
SET t += $data

// If new references are incoming, delete the old ones and update for new ones
DELETE tcr
DELETE tcar
DELETE tsr
DELETE tnr
MERGE (t)-[:references]->(cl)
MERGE (t)-[:references]->(ca)
MERGE (t)-[:references]->(s)
MERGE (t)-[:references]->(n)

WITH *

// Get the new count of revisions
MATCH (t)-[:assembled_with]->(_r:revision)

RETURN {
  uuid: t.uuid,
  start: t.start,
  end: t.end,
  description: t.description,
  client: CASE WHEN exists(cl.uuid) THEN {uuid: cl.uuid} ELSE NULL END,
  case: CASE WHEN exists(ca.uuid) THEN {uuid: ca.uuid} ELSE NULL END,
  step: CASE WHEN exists(s.uuid) THEN {uuid: s.uuid} ELSE NULL END,
  note: CASE WHEN exists(n.uuid) THEN {uuid: n.uuid} ELSE NULL END,
  revisions: count(_r)
}

2 个答案:

答案 0 :(得分:5)

APOC Procedures刚刚更新了对conditional cypher execution的支持。您需要3.1.3.7或更高版本(如果使用Neo4j 3.1.x)或版本3.2.0.3或更高版本(如果使用Neo4j 3.2.x)。

以下是您提到的一些案例的示例,使用新程序:

CALL apoc.when($refs.client IS NOT NULL, 
 "MATCH (cl:client {uuid: refs.client}) RETURN cl", '', {refs:$refs}) YIELD value
WITH value.cl as cl  // which might be null...
...

...
CALL apoc.do.when(cl IS NOT NULL, 
 "DELETE tcr 
  MERGE (t)-[:references]->(cl)", '', {tcr:tcr, t:t, cl:cl}) YIELD value
...

...
RETURN {
  client: cl {.uuid}, ...
}

在您的回访中,地图投影足以满足您的需求,如果cl存在,您将获得带有uuid的对象,如果不存在,则会获得client的空值。

答案 1 :(得分:1)

较旧的问题,但有一些新技巧可以实现条件 Cypher 执行,尤其是 Neo4j 4.1.x 中引入的子查询。

这篇知识库文章涵盖了可用的选项,随着其他方法的出现,我们会不断更新文章。

https://neo4j.com/developer/kb/conditional-cypher-execution/

请注意,我旧答案中的 APOC 方法仍然有效,并包含在文章中。

相关问题