Csv 基于最大和最小组列值在Neo4j图形中创建关系

Csv 基于最大和最小组列值在Neo4j图形中创建关系,csv,graph,neo4j,cypher,Csv,Graph,Neo4j,Cypher,我有一个结构与此类似的csv文件 elementID | groupID | sequence abc | A | 0 dcv | A | 1 asd | B | 0 ccc | B | 1 abc | B | 2 以及一个Neo4j图,其中与elementID和groupID相对应的节点已经用相应的ID创建 现在,我想从这个csv文

我有一个结构与此类似的csv文件

 elementID | groupID | sequence
     abc   |    A    |    0
     dcv   |    A    |    1
     asd   |    B    |    0
     ccc   |    B    |    1
     abc   |    B    |    2
以及一个Neo4j图,其中与
elementID
groupID
相对应的节点已经用相应的ID创建

现在,我想从这个csv文件创建一个从每个
(在csv文件中指示
组ID
)到
元素
节点(在csv文件中指示
元素ID
)的关系使用标签
:开始
如果
对应元组中的
序列
值为
0
,使用标签
:停止
如果
序列
值为该组的最大值

为了更清楚,考虑到上面的行,应创建以下关系:

(A)-[:STARTS]->(abc)
(A)-[:STOPS]->(dcv)
(B)-[:STARTS]->(asd)
(B)-[:STOPS]->(abc)
我已尝试使用以下内容创建
:START
关系:

LOAD CSV WITH HEADERS FROM "file:///file.csv" AS row
UNWIND KEYS(row) AS bid
WITH bid, row
WHERE bid="equence" AND TOINTEGER(row[bid]) = 0
MATCH (t:Group {Id: row.groupID})
MATCH (b:Element {Id: row.elementID})
WITH b, t
MERGE (t)-[:STARTS]->(b);
但这似乎要花很长时间

相反,我不知道从哪里开始,以便包装其他类型的关系


如何操作?

您可以按其名称访问行字段,因此不需要按以下键执行
展开操作:

LOAD CSV WITH HEADERS FROM "file:///file.csv" AS row
WITH row
WHERE toInteger(row.sequence) = 0
MATCH (t:Group {ID: row.groupID})
MATCH (b:Element {ID: row.elementID})
MERGE (t)-[:STARTS]->(b);
假设您有
:Group(ID)
:Element(ID)
上的索引,它应该相当快

使用
max
聚合查找最大元素并创建关系,这将在单个查询中创建两个关系:

LOAD CSV WITH HEADERS FROM "file:/file.csv" as line
WITH line.groupID as groupID, collect({elementID: line.elementID, sequence:toInteger(line.sequence)}) as groupElements,max(toInteger(line.sequence)) as max
UNWIND groupElements as element
MATCH (g:Group {ID:groupID}),(e:Element {ID:element.elementID})
FOREACH(ignoreMe IN CASE WHEN element.sequence = 0 THEN [1] ELSE [] END | CREATE (g)-[:STARTS]->(e))
FOREACH(ignoreMe IN CASE WHEN element.sequence = max THEN [1] ELSE [] END | CREATE (g)-[:STOPS]->(e))
它使用的技巧如下所述:

更新:如果有许多行的序列不是0和max,那么可以通过添加

WITH element,max,groupID
WHERE element.sequence = 0 OR element.sequence = max
就在
匹配之前
,这应该避免对这些行进行索引查找

关于FOREACH/CASE语法的更新:这是解决Cypher在该领域缺乏功能的一个办法

这是Cypher的if/then/else条件。但是,它是一个表达式(=返回值),不能包含写入操作。这正是我们所需要的

当序列等于0时,返回包含数字1的数组。如果顺序条件为真,则等同于:

FOREACH(ignoreMe IN [1] | CREATE (g)-[:STARTS]->(e))

它将为数组中的每个元素执行
|
之后的部分。该变量称为
ignoreMe
,因为它未被使用。如果条件为false,则数组为空,因此不会执行CREATE语句。

它可以工作,但我有几个问题。我得到这两个警告
此查询在断开连接的模式之间构建笛卡尔积。
此查询的执行计划包含渴望运算符,它强制在继续之前在主内存中具体化所有依赖数据。我猜
collect
正在按
line.groupID
创建一个列表分组,但我不理解FOREACH的语法。。万一。。然后[1]否则[0]…结束
如果您的ID是唯一的,则笛卡尔乘积为假阳性。是的,它需要将所有内容加载到内存中以进行最大聚合。关于foreach和case语法,请参阅更新。
FOREACH(ignoreMe IN [1] | CREATE (g)-[:STARTS]->(e))