我有以下节点
(Node:{Id=1,Prop1="A",TS=1})
(Node:{Id=2,Prop1="A",TS=25})
(Node:{Id=3,Prop1="A",TS=30})
(Node:{Id=4,Prop1="B",TS=1})
(Node:{Id=5,Prop1="B",TS=5})
(Node:{Id=6,Prop1="B",TS=1000})
...
我需要通过Prop1对它们进行分组,并将它们按照TS
的顺序进行链接Id=1->Id=2->Id=3
Id=4->Id=5->Id=6
...
答案 0 :(得分:2)
这是一个执行此操作的Cypher,其中的注释解释了每个部分。这应该比你在高容量情况下提出的解决方案稍微好一点(但是使用PROFILE来评估哪个对你的Neo4j / schema版本更有效)。
// Get all nodes to be linked
MATCH (n:A)
// Sort them by TS, split by group (id to define equal TS resolution)
WITH n, n.Prop1 as group
ORDER BY n.TS, id(n) ASC
// Collect nodes and keep them divided by group
WITH COLLECT(n) as list, group
// Split collection into this-next pairs
UNWIND RANGE(0,size(list) - 2) as index
WITH list[index] AS n1, list[index+1] AS n2
// Create relation between each pair
MERGE (n1)-[:NextNode]->(n2)
编辑: 以下是如何链接两个seprate组
MATCH (a{Prop1:"A"}) WITH a ORDER BY a.TS ASC WITH COLLECT(a)[-1] as start
MATCH (b{Prop1:"B"}) WITH start, b ORDER BY b.TS ASC WITH start, COLLECT(b)[0] as end
MERGE (start)-[:link]->(end)
答案 1 :(得分:2)
我发现使用apoc.coll.pairsMin()函数是生成要链接的节点列表的最简洁方法。
这样的东西应该可以在组内链接(未经测试,顺便说一句):
MATCH (n:Node)
WITH n
ORDER BY n.Prop1, n.TS
WITH n.Prop1 AS group, apoc.coll.pairsMin(COLLECT(n)) AS pairs
UNWIND pairs AS pair
WITH group, pair[0] AS start, pair[1] AS end
MERGE (start)-[:CONNECTED_TO]->(end)
RETURN group, COUNT(1) AS relationships
在阅读其他答案的一些评论之后,似乎您也希望在群组之间进行链接。
这是对上述查询的一个非常简单的更改,只是不要将它们分组开始(依赖于全局排序):
MATCH (n:Node)
WITH n
ORDER BY n.Prop1, n.TS
WITH apoc.coll.pairsMin(COLLECT(n)) AS pairs
UNWIND pairs AS pair
WITH pair[0] AS start, pair[1] AS end
MERGE (start)-[:CONNECTED_TO]->(end)
RETURN COUNT(1) AS relationships
答案 2 :(得分:1)
来自the comments:
[我尝试过]
MATCH (m1: Node) MATCH (m2: Node) WHERE m1.Prop1 = m2.Prop1 and m1.TS < m2.TS MERGE (m1)-[:CONNECTED_TO]->(m2)
但是它会创建链接 在ts = 1和ts = 3之间
将您的查询更改为:
MATCH (m1: Node) MATCH (m2: Node)
WHERE m1.Prop1 = m2.Prop1 and
m1.TS = m2.TS + 1
MERGE (m1)-[:CONNECTED_TO]->(m2)
即:将条件m1.TS < m2.TS
更改为m1.TS = m2.TS + 1
。