C# 如何使用cypher检索neo4j图中两个节点之间的唯一路径列表?
我在neo4j中有一个有向图,它有两种节点类型,比如a和B。基本上,在顶部a指向多个B,每个B指向多个a,递归向下。大概是这样的: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}"
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
。