条件 Cypher 执行

查询有时需要无法仅通过 Cypher 充分表达的条件执行逻辑。条件执行过程模拟了 if / else 结构,其中提供的布尔条件决定了执行哪个 Cypher 查询。

过程和函数概述

以下介绍了可用的过程和函数

限定名称 类型

apoc.when
apoc.when(condition BOOLEAN, ifQuery STRING, elseQuery STRING, params MAP<STRING, ANY>) - 如果条件评估为真,此过程将运行只读的 ifQuery,否则将运行 elseQuery

过程 (Procedure) Cypher 25 中已弃用

apoc.do.when
apoc.do.when(condition BOOLEAN, ifQuery STRING, elseQuery STRING, params MAP<STRING, ANY>) - 如果条件评估为真,则运行给定的读/写 ifQuery,否则运行 elseQuery

过程 (Procedure) Cypher 25 中已弃用

apoc.case
apoc.case(conditionals LIST<ANY>, elseQuery STRING, params MAP) - 对于给定 LIST<ANY> 中的每一对条件查询和只读查询,此过程将运行第一个条件评估为真的查询。如果没有条件为真,则改为运行 ELSE 查询。

过程 (Procedure) Cypher 25 中已弃用

apoc.do.case
apoc.do.case(conditionals LIST<ANY>, elseQuery STRING, params MAP<STRING, ANY>) - 对于给定 LIST<ANY> 中的每一对条件查询,此过程将运行第一个条件评估为真的查询。如果没有条件为真,则改为运行 ELSE 查询。

过程 (Procedure) Cypher 25 中已弃用

WHEN 过程

对于 if / else 条件逻辑,when 过程允许指定 ifQuery 和 elseQuery。如果条件为真,则运行 ifQuery;否则运行 elseQuery。

签名

apoc.when(condition :: BOOLEAN, ifQuery :: STRING, elseQuery = :: STRING, params = {} :: MAP) :: (value :: MAP)

apoc.do.when(condition :: BOOLEAN, ifQuery :: STRING, elseQuery = :: STRING, params = {} :: MAP) :: (value :: MAP)

只读
CALL apoc.when(
  condition: BOOLEAN,
  ifQuery: STRING,
  elseQuery: STRING,
  params: MAP)
YIELD value
写入
CALL apoc.do.when(
  condition: BOOLEAN,
  ifQuery: STRING,
  elseQuery: STRING,
  params: MAP)
YIELD value

例如,要匹配距离起始节点一跳和两跳的邻居节点,并返回较小的集合(即一跳距离的节点或两跳距离的节点),请运行以下查询

MATCH (start:Node)-[:REL]->(a)-[:REL]->(b)
WITH collect(distinct a) as aNodes, collect(distinct b) as bNodes

CALL apoc.when(
  size(aNodes) <= size(bNodes),
  'RETURN aNodes as resultNodes',
  'RETURN bNodes as resultNodes',
  {aNodes:aNodes, bNodes:bNodes})
YIELD value

RETURN value.resultNodes as resultNodes

若要在账户可能被视为可疑的情况下有条件地设置或创建图元素(同时继续进行其他查询操作),请使用 apoc.do.when 过程。

MATCH (acc:Account)
OPTIONAL MATCH (acc)-[r:ACCESSED_BY]->(suspect:User)
WHERE suspect.id in {suspiciousUsersIdList}

CALL apoc.do.when(
  r IS NOT NULL,
  'SET acc:Suspicious',
  '',
  {acc:acc})
YIELD value

// ignore value and continue
WITH acc
...

CASE 过程

对于更复杂的条件逻辑,case 过程允许使用变长列表的条件/查询对,其中会执行第一个评估结果为真的条件所对应的查询。如果没有任何条件为真,则执行 elseQuery 块。

签名

apoc.case(conditionals :: LIST<ANY>, elseQuery = :: STRING, params = {} :: MAP) :: (value :: MAP)

apoc.do.case(conditionals :: LIST<ANY>, elseQuery = :: STRING, params = {} :: MAP) :: (value :: MAP)

只读
CALL apoc.case(
  conditionals: List of alternating BOOLEAN/STRING,
  elseQuery: STRING,
  params: MAP)
YIELD value
写入
CALL apoc.do.case(
  conditionals: List of alternating BOOLEAN/STRING,
  elseQuery: STRING,
  params: MAP)
YIELD value

为了在列中匹配选择节点,可以根据查询参数或图中已有的数据使用不同的 MATCH 子句。

MATCH (me:User {id:$myId})
CALL apoc.case([
  $selection = 'friends', "RETURN [(me)-[:FRIENDS]-(friend) | friend] as selection",
  $selection = 'coworkers', "RETURN [(me)-[:WORKS_AT*2]-(coworker) | coworker] as selection",
  $selection = 'all', "RETURN apoc.coll.union([(me)-[:FRIENDS]-(friend) | friend], [(me)-[:WORKS_AT*2]-(coworker) | coworker]) as selection"],
  'RETURN [] as selection',
  {me:me}
)
YIELD value
RETURN value.selection as selection;

要根据值在两个节点之间创建不同的关系类型,请运行以下语句

MATCH (me:User {id:$myId})
MATCH (friend:User {id:$friendId})
CALL apoc.do.case([
  $selection = 'friends', "MERGE (me)-[rel:FRIENDS]->(friend) RETURN rel",
  $selection = 'coworkers', "MERGE (me)-[rel:CO_WORKER]->(friend) RETURN rel"],
  'MERGE (me)-[rel:CONNECTED]->(friend) RETURN rel',
  {me:me, friend:friend}
)
YIELD value
RETURN value.rel as rel;