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

C# 如何使用cypher检索neo4j图中两个节点之间的唯一路径列表?,c#,neo4j,neo4jclient,C#,Neo4j,Neo4jclient,我在neo4j中有一个有向图,它有两种节点类型,比如a和B。基本上,在顶部a指向多个B,每个B指向多个a,递归向下。大概是这样的: var dic = new Dictionary<string, object> {{a1.toString(), a1}, {a2.toString(), a2}}; var query = _graphClient.Cypher .Start(dic) .Match(String.Format("p={0}-[*]->{1}"

我在neo4j中有一个有向图,它有两种节点类型,比如a和B。基本上,在顶部a指向多个B,每个B指向多个a,递归向下。大概是这样的:

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();
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();
任何帮助都将是惊人的!提前谢谢你

更新

有了Christophe Willemsen的评论和这篇文章(),我能够得到以下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();
var query=\u graphClient.Cypher
.Match(“p=(a2:A)-[*]->(a1:A)”)
//Where和AndWhere用于根据需要匹配a1和a2
.Return(“节点(p)”)
.OrderByDescending(“长度(p)”)
.结果
.SelectMany(result=>newlist{result.ToList()});
返回query.ToList();

如果有人知道如何指定to节点(p)只返回A,那么应该这样做。我可以简单地遍历每个路径来删除B,但是如果有很多B,尤其是如果有一些漂亮的密码方法来实现,那么效率就不太高了。不过还是要谢谢你的帮助

您可以将allShortestPaths算法与distinct一起使用,如下所示:

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控制台设置为沙箱,可在此处使用:

顺便说一句,我很难从结果中删除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

克里斯

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

顺便说一句,在尝试查找此查询时,我发现以下内容:

在尝试筛选节点集合(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

nodes(p)
已经返回了一个集合,如果您再次
collect
它,您将拥有
p
中所有节点集合的(单个元素)集合。如果你不收集,你也不必在过滤前放松,但你可以马上过滤
a:a
也是一个有效的谓词,因此您可以用这种方法来测试,而不是在
labels
中测试标签的字符串表示形式。下面是它的样子:使用标签过滤
节点(p)
的密码应该是
filter(n在节点(p)中,其中n:a)
。如果必须使用
.Filter
方法,或者可以将cypher Filter函数添加到作为参数传递给
的字符串中,则不确定如何在fluent cypher客户端中执行此操作。Return