Cypher:返回与不匹配的节点匹配的节点

时间:2017-07-21 19:30:29

标签: neo4j cypher

使用标签A,B和Z,A和B与Z有自己的关系。使用查询

MATCH (a:A)
MATCH (b:B { uuid: {id} })
MATCH (a)-[:rel1]->(z:Z)<-[:rel2]-(b)
WITH a, COLLECT(z) AS matched_z
RETURN DISTINCT a, matched_z

返回A的节点和与A和B有关系的所有节点Z

我一直试图返回一个单独的Z节点数组,B与Z有,但没有A(即missing_z)。我正在尝试进行初始查询以返回B&amp; B之间的所有关系。 ž

results = MATCH (b:B { uuid: {id} })
MATCH (b)-[:rel2]->(z:Z)
RETURN DISTINCT COLLECT(z.uuid) AS z

MATCH (a:A)
MATCH (b:B { uuid: {id} })
MATCH (a)-[:rel1]->(z:Z)<-[:rel2]-(b)
WITH a, COLLECT(z) AS matched_z, z
RETURN DISTINCT a, matched_z, filter(skill IN z.array WHERE NOT z.uuid IN {results}) AS missing_z

对于missing_z,结果似乎没有结果,人们会认为应该填充它。不确定过滤器是否是使用WHERE NOT / IN方案的正确方法。上述2个查询可以合并为1吗?

2 个答案:

答案 0 :(得分:1)

在我看来,这里的难点在于任何失败的比赛都会丢弃到目前为止你所匹配的所有内容。但是你的出发点似乎是&#34;所有Z与B.uuid&#34;相关,所以首先从那里收集并过滤/复制。

使用WITH +聚合函数复制+过滤列

如果匹配失败,请使用OPTIONAL MATCH不应删除已收集的行。

如果我理解你要做的事情,那么这个密码应该完成这个工作,并根据需要调整它(如果你需要帮助理解它的任何部分/适应它,请告诉我)

// Match base set
MATCH (z:Z)<-[:rel2]-(b:B { uuid: {id} })
// Collect into single list
WITH COLLECT(z) as zs
// Match all A (ignore relation to Zs) 
MATCH (a:A)
// For each a, return a, the sub-list of Zs related to a, and the sub-list of Zs not related to a
RETURN a as a, FILTER(n in zs WHERE (a)-[:rel1]->(n)) as matched, FILTER(n in zs WHERE NOT (a)-[:rel1]->(n)) as unmatched

答案 1 :(得分:0)

此查询可能会执行您想要的操作:

MATCH (z:Z)<-[:rel2]-(b:B { uuid: {id} })
WITH COLLECT(z) as all_zs
UNWIND all_zs AS z
MATCH (a)-[:rel1]->(z)
WITH all_zs, COLLECT(DISTINCT z) AS matched_zs
RETURN matched_zs, apoc.coll.subtract(all_zs, matched_zs) AS missing_zs;

它首先在all_zs变量中存储与Z具有rel2关系的所有b个节点。即使第二个MATCH子句匹配那些Z节点的子集,此集合的内容也不会受到影响。

然后,它会在matched_zsall_zs节点中存储与rel1个节点具有A关系的不同matched_zs个节点。

最后,它返回:

  • all_zs集合,
  • matched_zs中不属于missing_zs的唯一节点,{{1}}。

查询使用方便的APOC函数apoc.coll.subtract来生成后一个返回值。