在 neo4j 中导入多个 csv 的有效方法
Efficient way to import multiple csv's in neo4j
我正在为 CALL 数据集在 neo4j 中创建图形数据库。数据集存储在包含以下列的 csv 文件中:源、目标、时间戳、持续时间。这里 Source 和 Target 是 Person id(数字),Timestamp 是日期时间,持续时间以秒为单位(整数)。
我为我的图表建模,其中人是节点(person_id 作为 属性),调用作为关系(时间和持续时间作为 属性)。
大约有 2,00,000 个节点和大约 7000 万个关系。我有一个单独的 csv 文件,其中包含用于创建节点的人员 ID。我还在 Person id 上添加了唯一性约束。
CREATE CONSTRAINT ON ( person:Person ) ASSERT (person.pid) IS UNIQUE
我不完全理解批量导入的工作原理,所以我写了一个 python 脚本将我的 csv 分成 70 个 csv,其中每个 csv 有 100 万个节点(另存为 calls_0,calls_1, .... calls_69).我主动手动 运行 每次更改文件名的密码查询。它对前几个(大约 10 个)文件运行良好(足够快),但后来我注意到在从一个文件添加关系后,下一个文件的导入速度变慢了。现在导入一个文件需要将近 25 分钟。
有人可以 link 告诉我一个高效简单的方法吗?
这里是密码查询:
:auto USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM 'file:///calls/calls_28.csv' AS line
WITH toInteger(line.Source) AS Source,
datetime(replace(line.Time,' ','T')) AS time,
toInteger(line.Target) AS Target,
toInteger(line.Duration) AS Duration
MATCH (p1:Person {pid: Source})
MATCH (p2:Person {pid: Target})
MERGE (p1)-[rel:CALLS {time: time, duration: Duration}]->(p2)
RETURN count(rel)
我正在使用 Neo4j 4.0.3
您的 MERGE
子句必须检查现有的匹配关系(以避免创建重复项)。如果您在 Person
节点之间添加了 很多 关系,这可能会使 MERGE
子句变慢。
您应该考虑使用 CREATE
代替 MERGE
是否安全。
如果使用每个节点的 ID 导出匹配项然后创建关系会更好。
POC
CREATE INDEX ON :Person(`pid`);
CALL apoc.export.csv.query("LOAD CSV WITH HEADERS FROM 'file:///calls/calls_28.csv' AS line
WITH toInteger(line.Source) AS Source,
datetime(replace(line.Time,' ','T')) AS time,
toInteger(line.Target) AS Target,
toInteger(line.Duration) AS Duration
MATCH (p1:Person {pid: Source})
MATCH (p2:Person {pid: Target})
RETURN ID(a) AS ida,ID(b) as idb,time,Duration","rels.csv", {});
然后是
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM 'file:////rels.csv' AS row
MATCH (a:Person) WHERE ID(a) = toInt(row.ida)
MATCH (b:Person) WHERE ID(b) = toInt(row.idb)
MERGE (b)-[:CALLS {time: row.time, duration: Duration}]->(a);
对我来说,这是最好的方法。
我正在为 CALL 数据集在 neo4j 中创建图形数据库。数据集存储在包含以下列的 csv 文件中:源、目标、时间戳、持续时间。这里 Source 和 Target 是 Person id(数字),Timestamp 是日期时间,持续时间以秒为单位(整数)。
我为我的图表建模,其中人是节点(person_id 作为 属性),调用作为关系(时间和持续时间作为 属性)。 大约有 2,00,000 个节点和大约 7000 万个关系。我有一个单独的 csv 文件,其中包含用于创建节点的人员 ID。我还在 Person id 上添加了唯一性约束。
CREATE CONSTRAINT ON ( person:Person ) ASSERT (person.pid) IS UNIQUE
我不完全理解批量导入的工作原理,所以我写了一个 python 脚本将我的 csv 分成 70 个 csv,其中每个 csv 有 100 万个节点(另存为 calls_0,calls_1, .... calls_69).我主动手动 运行 每次更改文件名的密码查询。它对前几个(大约 10 个)文件运行良好(足够快),但后来我注意到在从一个文件添加关系后,下一个文件的导入速度变慢了。现在导入一个文件需要将近 25 分钟。 有人可以 link 告诉我一个高效简单的方法吗?
这里是密码查询:
:auto USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM 'file:///calls/calls_28.csv' AS line
WITH toInteger(line.Source) AS Source,
datetime(replace(line.Time,' ','T')) AS time,
toInteger(line.Target) AS Target,
toInteger(line.Duration) AS Duration
MATCH (p1:Person {pid: Source})
MATCH (p2:Person {pid: Target})
MERGE (p1)-[rel:CALLS {time: time, duration: Duration}]->(p2)
RETURN count(rel)
我正在使用 Neo4j 4.0.3
您的 MERGE
子句必须检查现有的匹配关系(以避免创建重复项)。如果您在 Person
节点之间添加了 很多 关系,这可能会使 MERGE
子句变慢。
您应该考虑使用 CREATE
代替 MERGE
是否安全。
如果使用每个节点的 ID 导出匹配项然后创建关系会更好。
POC
CREATE INDEX ON :Person(`pid`);
CALL apoc.export.csv.query("LOAD CSV WITH HEADERS FROM 'file:///calls/calls_28.csv' AS line
WITH toInteger(line.Source) AS Source,
datetime(replace(line.Time,' ','T')) AS time,
toInteger(line.Target) AS Target,
toInteger(line.Duration) AS Duration
MATCH (p1:Person {pid: Source})
MATCH (p2:Person {pid: Target})
RETURN ID(a) AS ida,ID(b) as idb,time,Duration","rels.csv", {});
然后是
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM 'file:////rels.csv' AS row
MATCH (a:Person) WHERE ID(a) = toInt(row.ida)
MATCH (b:Person) WHERE ID(b) = toInt(row.idb)
MERGE (b)-[:CALLS {time: row.time, duration: Duration}]->(a);
对我来说,这是最好的方法。