Graph Neo4j Cypher:除了常规排序之外的拓扑排序?

Graph Neo4j Cypher:除了常规排序之外的拓扑排序?,graph,neo4j,cypher,Graph,Neo4j,Cypher,假设我有一个如下所示的节点树: 其中,数字对应于我通常想要排序的某个值。(可能是时间,可能是某种分数,随便什么。) 如果我返回按该数字排序的数据,我当然会得到这样的排序: 1, 2, 3, 4, 5, 6, 7, 8, 9 3, 2, 1, 4, 5, 6, 7, 8, 9 一般来说,这很好,但是除了这种排序之外,我想应用约束,即父母总是在他们的孩子之前排序。所以我真正想要的是这种: 1, 2, 3, 4, 5, 6, 7, 8, 9 3, 2, 1, 4, 5, 6, 7, 8, 9

假设我有一个如下所示的节点树:

其中,数字对应于我通常想要排序的某个值。(可能是时间,可能是某种分数,随便什么。)

如果我返回按该数字排序的数据,我当然会得到这样的排序:

1, 2, 3, 4, 5, 6, 7, 8, 9
3, 2, 1, 4, 5, 6, 7, 8, 9
一般来说,这很好,但是除了这种排序之外,我想应用约束,即父母总是在他们的孩子之前排序。所以我真正想要的是这种:

1, 2, 3, 4, 5, 6, 7, 8, 9
3, 2, 1, 4, 5, 6, 7, 8, 9
你可以看到这看起来几乎一样;我们刚刚将
1,2,3
的顺序翻转到
3,2,1

有没有办法通过Neo4j密码查询实现这种排序?

-

下面是一个带有此树的实时控制台示例:

以下是我目前的疑问:

MATCH path=( ({i: 3}) <-[:parent*0..]- (node) )
RETURN node, node.i, LENGTH(path)

MATCH path=({i:3})您可以将这两个值组合起来表示排序顺序,只需给父级一个更高的优先级:

MATCH path =((root:Node { i: 3 })<-[:parent*0..]-(node:Node))
RETURN node, node.i, LENGTH(path)
ORDER BY LENGTH(path)+ node.id *10

我没有使用Neo4j的经验,但如果我理解正确,下面的算法,换句话说,符合您的描述。祝您好运

从根节点开始,将根作为下一个值复制到排序列表中。在根的子节点中进行选择,选择“下一个根”作为根的最小子节点。将根替换为“下一个根”,并将所有“下一个根”子节点上移一级。重复操作,直到图形为空

例:


这感觉有点粗糙,但可能会奏效,这取决于您的树的大小的可预测性:

MATCH path=(root:Node { i: 3 })<-[:parent*0..]-(node:Node)
WITH nodes(path)[-1] as n,[x IN nodes(path)| x.i] AS o
ORDER BY o[0], coalesce(o[1], -1), coalesce(o[2], -1), coalesce(o[3], -1) // and so forth
RETURN n

您可以获得如图所示的最大路径长度,也可以将maxLen设置为一个非常高的数字。

谢谢您的快速回答,Michael,但我认为这是不对的。属性是
I
,而不是
id
;当我修复您的查询以使用它时,排序是不同的。我认为部分问题在于
长度(路径)
我真正关心的不是孤立的问题,而是节点之间的父子关系。OP没有要求一个算法。基本上你在一个密码查询中说明了他已经在要求什么。谢谢各位。我同意我知道一般的算法,但在这里看到一个算法并不是没有帮助的。=)如果我们认为这在Cypher中是不可能的,那么我们可以在Gremlin中实现这一点。
合并的数量需要是树的高度吗?如果是这样的话,我们不能提前预测高度。但是我想我可以先预先编写一个查询来推导高度,然后用它来计算高度?如果你有太多,那没关系,你只需要把合并的数量设为最大高度。你只是不想对一棵很深的树这样做,否则查询会很难看。顺便说一句,这是惊人的-实际上是一个宽度优先的顺序。你真的是一个密码神!=)帮助我看到这一点的演示链接:嗯,我们也无法预测最大高度,所以我们将硬编码一些东西,例如100,希望我们不会超过这个值。但这很脆弱。有什么方法可以适应动态高度吗?我突然想到,此时您可以使用
节点
,而不是
节点(路径)[-1]
MATCH path=(root:Node { i: 3 })<-[:parent*0..]-(node:Node)
WITH nodes(path)[-1] AS n,[x IN nodes(path)| x.i] AS o, 
     reduce(maxLen=0, p IN root<-[:parent*]-()|CASE WHEN maxLen < length(p)
                                                   THEN length(p)
                                                   ELSE maxLen END ) AS maxLen
ORDER BY reduce(acc='', x IN range(0,maxLen)|acc+coalesce(str(o[x]), ''))
RETURN n,reduce(acc='', x IN range(0,maxLen)|acc+coalesce(str(o[x]), ''))