neo4j从已知节点获取随机路径

时间:2017-12-26 08:35:24

标签: neo4j cypher

我有一个很大的neo4j数据库,其中有关于明星的信息,他们都与其他许多人有关系,他们是相互联系,约会,彼此结婚。所以我需要从一个名人那里得到随机路径,并定义关系数(5)。我不在乎谁会在这个链条中,我唯一的条件就是不应该在链条中重复明星。

更清楚:我需要在每次查询后获得“新”链,例如:

  • 我尝试用Rita Ora开始连锁
  • 她与...有关系 Drake,Jay Z和Justin Bieber
  • 查询从这些人那里随机抽取,例如Jay Z
  • 然后查询采用Jay Z:Karrine的关系 Steffans,Rosario Dawson和Rita Ora
  • 查询不能带Rita Ora cuz 她已经处于连锁状态,因此从其他两个人那里随机抽取 示例Rosario Dawson
  • ...
  • 最后我们应该有一个链Rita Ora - Jay Z - Rosario Dawson - 其他名人 - 其他名人2

可以通过查询来实现吗?

1 个答案:

答案 0 :(得分:1)

这在Cypher中是可行的,但它非常棘手。你提到

  

我唯一的条件我不应该在链条中重复出现明星。

可以通过使用节点 - 同构模式匹配来捕获此条件,这需要路径中的所有节点都是唯一的。不幸的是,Cypher尚未支持此功能。它是proposed as part of the openCypher project,但仍在进行中。目前,Cypher仅支持relationship uniqueness,这对于这个用例是不够的,因为有多种关系类型(例如A与B结合,但B也与A合作,所以我们已经有一个只有两个节点的副本)。

APOC解决方案。如果您可以使用APOC库,请查看path expander,它支持各种唯一性约束,包括NODE_GLOBAL

Plain Cypher解决方案。要解决此限制,您可以使用过滤操作捕获节点唯一性约束:

MATCH p = (c1:Celebrity {name: 'Rita Ora'})-[*5]-(c2:Celebrity)
UNWIND nodes(p) AS node
WITH p, count(DISTINCT node) AS countNodes
WHERE countNodes = 5
RETURN p
LIMIT 1

性能方面,只要限制其结果,这应该没问题,因为查询引擎基本上会一直枚举新路径,直到其中一个路径通过过滤测试。

UNWIND nodes(p) AS node WITH count(DISTINCT node) ...构造的目标是首先从节点列表中删除重复项UNWIND-ing以分隔行,然后aggregating them to a unique collection using DISTINCT。然后我们检查唯一节点列表是否仍有5个元素 - 如果是,原始列表也是唯一的,我们RETURN结果。

注意。而不是UNWINDcount(DISTINCT ...),从列表中获取唯一元素可以用其他方式表达:

(1)使用list comprehension和范围:

WITH [1, 2, 2, 3, 2] AS l
RETURN [i IN range(0, length(l)-1) WHERE NOT l[i] IN l[0..i] | l[i]]

(2)使用reduce

WITH [1, 2, 2, 3, 2] AS l
RETURN reduce(acc = [], i IN l | acc + CASE NOT i IN acc WHEN true THEN [i] ELSE [] END)

但是,我认为这两种形式的可读性都低于原始形式。