我正在寻找一种在Neo4j中进行injective匹配的有效方法。如果你不确定我的意思;我只是希望返回匹配匹配中每个返回节点唯一的匹配(例如,具有唯一ID),并且路径相同。
使用维基百科(上图)中的图表,匹配的域X是模式中的节点和路径,共域Y是数据库的内部图。上图是单射的,因为X中没有2个箭头指向Y中的相同元素(因此图中没有2个节点与图中的同一节点匹配,而边缘也相同),而默认的Neo4J匹配是非-injective并允许模式中的2个节点与图中的相同节点匹配(您可以将非内射匹配的示例可视化为X中的1和2中的箭头,均指向上图中的Y中的D) 。传统图论将调用匹配域X中的多个项目到共域Y“合并”中的相同项目,但我可以理解该术语在这种情况下可能会令人困惑。
我可以通过指定匹配的节点是不同的来模拟特定查询:
match (a), (b) where not id(a) = id(b) return a, b
但我希望在一般意义上做到这一点,而不必在每个查询中都明确这一点。所以对于这个例子,我想返回匹配,其中(a)和(b)是唯一的节点,但我想用一些一般的行为来做,而不是根据ID指定唯一性。
当我查询时,似乎路径已经保证是唯一的,但是如果有人能够确认那将是很好的。
答案 0 :(得分:1)
我不确定您到底想要什么,但我可以升级您的查询以提高效率。
Match (a),(b) where id(a) < id(b)
Return a,b
如果要返回不同的节点或关系,则密码具有distinct
函数。例如:
Match (a)-->(b)
Return distinct(a)
P.S。总是使用节点标签,因为它加快了查询执行速度
答案 1 :(得分:1)
如果您只想确保匹配中变量的节点不相同,则可以安装APOC Procedures并使用collection helper functions中的某些节点,特别是apoc.coll.containsDuplicates()
。
示例用法可能如下所示:
MATCH p1=(a)-[r]->(b), (c)
WHERE NOT apoc.coll.containsDuplicates([a, b, c])
RETURN a, b, c, p1
答案 2 :(得分:0)
编辑:@InverseFalcon使用APOC插件提供了更好的解决方案,但如果您因任何原因无法使用APOC或APOC支持停止,那么您可以手动检查ID的唯一性,如此处所述。
路径在设计上是独一无二的,因此可以通过简单地确保节点是唯一的来实现内射匹配。从this answer中获取灵感,显然你无法包装查询来实现这一点,但WHERE子句中的简短ALL语句至少简化了id检查。
如果要匹配的模式由:
描述MATCH p1=(a)-[r]->(b), (c)
RETURN a, b, c, p1
这是一个非常简单的(任何3个节点,从第1个到第2个具有任何关系)模式,然后您可以通过检查每个节点的ID与其他节点来确保这3个节点的唯一性:
MATCH p1=(a)-[r]->(b), (c)
WHERE ALL(n in [a, b, c] where
1=length(filter(m in [a, b, c] where id(m)=id(n))))
RETURN a, b, c, p1
这通过检查我们希望唯一的节点集合中的每个节点([a,b,c])并将其ID与该集合中的每个其他节点的ID进行比较,确保存在集合中只有1个匹配的ID(本身)。这就是&#34;其中1 = length()&#34;部分。
因此,通常使用这种想法,保证返回的节点是唯一的,并且保证模式返回的路径是唯一的(通过Neo4j的设计)使得匹配过程是单射的。
它不是一个理想的解决方案,因为语句必须是从查询中自定义编写的,但它至少是一个WHERE条件,它与节点数线性增长,而不是为每对节点创建一个条件其中条件数按因子顺序增加到节点数。