如何使用cypher检索neo4j图中两个节点之间的唯一路径列表?

时间:2014-07-21 19:54:25

标签: c# neo4j neo4jclient

所以我在neo4j中有一个有向图,它有两个节点类型,比如A和B.基本上在顶部A指向很多B,每个都指向许多A,递归地向下。像这样:

A1 - > B1,B2,B3

B1 - > A3,A4,A7

B2 - > A5,A6,A8

A3 - > B3

A4 - > B3

A5 - > B3

B3 - > A9

无论如何,考虑到两个不同的A,我想运行一个查询来找出这两个A之间的所有独特路径。因此从上面给出A1和A9,我希望以下输出:

A1 - > B1 - > A3 - > B3 - > A9,

A1 - > B1 - > A4 - > B3 - > A9,

A1 - > B2 - > A5 - > B3 - > A9,

A1 - > B3 - > A9

如果可能的话,我也想从同一个查询中删除B(因为它们对于这个特定情况不是必需的),所以最终结果如下:

A1 - > A3 - > A9,

A1 - > A4 - > A9,

A1 - > A5 - > A9,

A1 - > A9

如果没有,我可以手动完成,但在查询中显然会更好。我究竟如何形成该查询?

到目前为止,我有这样的事情:

var dic = new Dictionary<string, object> {{a1.toString(), a1}, {a2.toString(), a2}};

var query = _graphClient.Cypher
    .Start(dic)
    .Match(String.Format("p={0}-[*]->{1}", a1.toString(), a2.toString()))
    //I don't know what goes here exactly... .Return(something)
    .Results;

return query.Single();

我认为我需要对多个密码查询做一些事情才能删除B。也许就像使用它作为中介并将其应用到任何深度:

a1-[]->b-[]->a2
return a1, a2;

任何帮助都会很棒!提前谢谢!!!

更新

使用Christophe Willemsen的评论和这篇文章(Neo4j .NET Client - Getting a Path from a Node to its Root),我能够获得以下c#代码,除了从路径中移除B之外的所有内容:

var query = _graphClient.Cypher
    .Match("p = (a2:A)-[*]->(a1:A)")
    //Where and AndWhere's for matching a1 and a2 as necessary
    .Return<IEnumerable<A>>("nodes(p)")
    .OrderByDescending("length(p)")
    .Results
    .SelectMany(result => new List<List<A>> {result.ToList()});

return query.ToList();

如果有人知道如何指定节点(p)只返回A,那应该这样做。我可以简单地遍历删除B的每个路径,但如果有很多这样的话,那就不是非常有效,特别是如果有一些漂亮的密码方式可以做到这一点。到目前为止,感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

你可以使用allShortestPaths算法,也可以像这样使用:

MATCH (a:A { name:'A1' }),(aa:A { name:'A8' }), p = allShortestPaths((a)-[*]-(aa))

RETURN DISTINCT (p), collect(nodes(p)) AS x

ORDER BY length(p) DESC 

LIMIT 5

我已经在这里设置了一个neo4j控制台作为沙箱:http://console.neo4j.org/?id=pjf2qg

我很难如何从结果btw

中删除B节点

更新

我最终只从路径中提取A标记化节点:

MATCH (a:A {name:'A1'}),(aa:A {name:'A8'}),
p = allShortestPaths((a)-[*]-(aa))
WITH DISTINCT(p) as pths, COLLECT(nodes(p)) as x
UNWIND(x) as u
WITH FILTER(s IN u WHERE 'A' IN labels(s)) AS zz, pths as paths
RETURN paths, zz

克里斯

答案 1 :(得分:0)

我的第一个答案是用一个有效的查询编辑的。

BTW在尝试查找此查询时,我发现了以下内容:

当尝试过滤节点集合(p)时,如果没有展开,标识符不会被视为节点,而是作为集合,我不知道它是否是预期的行为:

以下查询将失败,表示标识符s是集合,而预期是节点

MATCH (a:A {name:'A1'}),(aa:A {name:'A8'}),
p = allShortestPaths((a)-[*]-(aa))
WITH p as paths, COLLECT(nodes(p)) as x
WITH filter(s IN x WHERE 'A' IN labels(s)) AS zz
RETURN zz