首页 > 解决方案 > 一组节点之间的 Neo4J 连接和推荐

问题描述

我的数据库包含一组节点和一个数字类型的关系。给定一组节点,我想看看它们是否以及如何相互连接,并找到可以包含的节点。很抱歉无法合成数据。你可以把每个节点想象成一个城市,关系就是一个距离。如果关系不存在,则意味着从城市 A 到 B 没有直接的路径。这个想法有两个方面 1) 找出这些城市是否以及如何连接。2)寻找其他中间城市。

例如,如果我有 A、B、C、D 和 E - 一种方法是做一个成对的最短距离。该图是无方向的,因此 AB 与 BA 相同。

MATCH (n:people {name:'A'})-[r:INTERACTION]-(n2:people {name:'B'}),
      p = shortestPath ((n)-[*]-(n2))
RETURN p

但是,(n*n-1)/2我可以做这样的事情,而不是那样做:

MATCH (n:people)-[r:INTERACTION]-(n2:people)
MATCH spath=shortestPath ((n)-[*]-(n2))
WHERE n.name in ['A', 'B', 'C', 'D', 'E'] and n2.name in ['A', 'B', 'C', 'D', 'E']
RETURN DISTINCT n.name, n2.name, r.score 

尽管如此,对于第二个目标,寻找其他中间城市,我想知道在 neo4j 中是否有任何其他概念可以进行此类分析,如果没有,您将如何确保每对的输出是不同的,这意味着没有 AB和BA出来的,而只是其中之一。

标签: neo4jcypherigraphgraph-databases

解决方案


当然,如果您有一组数据,并且您想对不包含重复项的唯一集执行某些操作,那么最好先生成该唯一项集,然后将其传递给您的查询,这样您就不必执行不必要的查询,然后丢弃冗余信息。

要生成一组独特的对组,您可以执行以下操作。

// unwind the name collection twice to get all combinations
WITH ['A', 'B', 'C', 'D', 'E'] AS names
UNWIND names AS name1
UNWIND names AS name2

// makes sure the pairs are ordered and ignore identical pairs
WITH CASE 
       WHEN name1 = name2 THEN NULL 
       WHEN name2 < name1 THEN [name2, name1] 
       ELSE [name1, name2] 
     END AS pair

// collect all of the pairs
RETURN COLLECT (DISTINCT pair) AS pairs

如果您使用的是 APOC,则可以将其替换为

WITH ['A', 'B', 'C', 'D', 'E'] AS names
RETURN apoc.coll.combinations(names, 2) AS pairs

把它和你的查询放在一起,你可以做这样的事情......

// from above
WITH ['A', 'B', 'C', 'D', 'E'] AS names
UNWIND names AS name1
UNWIND names AS name2
WITH CASE WHEN name1 = name2 THEN NULL WHEN name2 < name1 THEN [name2, name1] ELSE [name1, name2] END AS pair
WITH COLLECT (DISTINCT pair) AS pairs

// iterate over the unique pairs
UNWIND pairs AS pair

// find the shortest path 
// from  
// the first node identified by the first value in the pair
// to 
// the second node identified by the second value in the pair
MATCH spath = shortestPath((:people {name: pair[0]} )-[*..5]-(:people {name: pair[1]} ))

// produce a string representation of each path 
RETURN reduce(string = "", rel in relationships(spath) | string + startNode(rel).name + " " + type(rel) + " " + endNode(rel).name + ", ")

此查询将返回您的“目的地”集中的最小路径集,而不会重复。


推荐阅读