apoc.export.cypher.data过程
|
此过程不建议在多线程中运行,因此并行运行时(Parallel runtime)不支持该过程。有关更多信息,请参阅 Cypher 手册 → 并行运行时。 |
语法 |
|
||
描述 |
将给定的 |
||
输入参数 |
名称 |
类型 |
描述 |
|
|
要导出的节点列表。 |
|
|
|
要导出的关系列表。 |
|
|
|
数据导出到的文件名。默认值为:``。 |
|
|
|
|
|
返回参数 |
名称 |
类型 |
描述 |
|
|
数据导出到的文件名。 |
|
|
|
导出过程执行的批次数。 |
|
|
|
导出数据的摘要。 |
|
|
|
文件的导出格式。 |
|
|
|
已导出节点的数量。 |
|
|
|
已导出关系的数量。 |
|
|
|
已导出属性的数量。 |
|
|
|
导出所花费的时间。 |
|
|
|
返回的行数。 |
|
|
|
导出过程执行的批处理大小。 |
|
|
|
已执行的 Cypher 语句。 |
|
|
|
已执行的节点语句。 |
|
|
|
已执行的关系语句。 |
|
|
|
已执行的模式(Schema)语句。 |
|
|
|
已执行的清理语句。 |
|
配置参数
该过程支持以下配置参数
| 名称 | 类型 | 默认 | 描述 |
|---|---|---|---|
|
|
false |
如果为 true,则也导出属性。 |
|
|
false |
将 json 直接流式传输到客户端的 |
|
|
cypher-shell |
导出格式。支持以下值:
|
|
|
create |
Cypher 更新操作类型。支持以下值:
|
useOptimizations |
MAP |
|
用于生成 Cypher 语句的优化配置。
|
|
|
300 |
当使用 |
|
|
false |
如果为 true,则在约束和索引中添加 |
导出到文件
默认情况下,导出到文件系统是被禁用的。我们可以通过在 apoc.conf 中设置以下属性来启用它:
apoc.export.file.enabled=true
有关访问 apoc.conf 的更多信息,请参阅配置选项章节。
如果我们尝试在未先设置此属性的情况下使用任何导出过程,我们将收到以下错误消息:
Failed to invoke procedure: Caused by: java.lang.RuntimeException: Export to files not enabled, please set apoc.export.file.enabled=true in your apoc.conf. Otherwise, if you are running in a cloud environment without filesystem access, use the |
导出文件被写入 import 目录,该目录由 server.directories.import 属性定义。这意味着我们提供的任何文件路径都是相对于此目录的。如果我们尝试写入绝对路径(例如 /tmp/filename),我们将收到类似于以下内容的错误消息:
Failed to invoke procedure: Caused by: java.io.FileNotFoundException: /path/to/neo4j/import/tmp/fileName (No such file or directory) |
我们可以通过在 apoc.conf 中设置以下属性来允许写入文件系统上的任何位置:
apoc.import.file.use_neo4j_config=false
|
Neo4j 现在将能够写入文件系统上的任何位置,因此在设置此属性之前,请确保这是您的意图。 |
使用示例
本节中的示例基于以下示例图
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})
CREATE (Laurence:Person {name:'Laurence Fishburne', born:1961})
CREATE (Hugo:Person {name:'Hugo Weaving', born:1960})
CREATE (LillyW:Person {name:'Lilly Wachowski', born:1967})
CREATE (LanaW:Person {name:'Lana Wachowski', born:1965})
CREATE (JoelS:Person {name:'Joel Silver', born:1952})
CREATE
(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),
(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix),
(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix),
(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix),
(LillyW)-[:DIRECTED]->(TheMatrix),
(LanaW)-[:DIRECTED]->(TheMatrix),
(JoelS)-[:PRODUCED]->(TheMatrix);
下方的 Neo4j Browser 可视化显示了导入的图
导出至 Cypher 的过程会使用 CREATE、MATCH 和 MERGE 子句生成 Cypher 语句。格式由 cypherFormat 参数配置。支持以下值:
-
create- 仅使用CREATE子句(默认) -
updateAll- 使用MERGE代替CREATE -
addStructure- 对节点使用MATCH,对关系使用MERGE -
updateStructure- 对节点和关系均使用MERGE和MATCH
如果是首次导出数据库,我们应该使用默认的 create 格式,但对于后续的导出,其他格式可能更合适。
以下示例使用 create 格式将 ACTED_IN 关系及相关节点导出到 export-cypher-format-create.cypher
MATCH (person)-[r:ACTED_IN]->(movie)
WITH collect(DISTINCT person) + collect(DISTINCT movie) AS importNodes, collect(r) AS importRels
CALL apoc.export.cypher.data(importNodes, importRels,
"export-cypher-format-create.cypher",
{ format: "plain", cypherFormat: "create" })
YIELD file, batches, source, format, nodes, relationships, properties, time, rows, batchSize
RETURN file, batches, source, format, nodes, relationships, properties, time, rows, batchSize;
| file | batches | source | format | 节点 | relationships | 属性 | time | rows | batchSize |
|---|---|---|---|---|---|---|---|---|---|
"export-cypher-format-create.cypher" |
1 |
"data: nodes(5), rels(4)" |
"cypher" |
5 |
4 |
15 |
2 |
9 |
20000 |
CREATE CONSTRAINT uniqueConstraint FOR (node:`UNIQUE IMPORT LABEL`) REQUIRE (node.`UNIQUE IMPORT ID`) IS UNIQUE;
UNWIND [{_id:0, properties:{tagline:"Welcome to the Real World", title:"The Matrix", released:1999}}] AS row
CREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Movie;
UNWIND [{_id:7, properties:{born:1967, name:"Carrie-Anne Moss"}},
{_id:80, properties:{born:1960, name:"Hugo Weaving"}},
{_id:27, properties:{born:1964, name:"Keanu Reeves"}},
{_id:44, properties:{born:1961, name:"Laurence Fishburne"}}] AS row
CREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Person;
UNWIND [{start: {_id:27}, end: {_id:0}, properties:{roles:["Neo"]}},
{start: {_id:7}, end: {_id:0}, properties:{roles:["Trinity"]}},
{start: {_id:44}, end: {_id:0}, properties:{roles:["Morpheus"]}},
{start: {_id:80}, end: {_id:0}, properties:{roles:["Agent Smith"]}}] AS row
MATCH (start:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.start._id})
MATCH (end:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.end._id})
CREATE (start)-[r:ACTED_IN]->(end) SET r += row.properties;
MATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 20000 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;
DROP CONSTRAINT uniqueConstraint;
所有图实体的创建均使用 Cypher 的 CREATE 子句。如果这些实体在目标数据库中可能已经存在,我们可以选择使用其他格式。使用 cypherFormat: "updateAll" 意味着在创建实体时将使用 MERGE 子句代替 CREATE。
以下示例使用 updateAll 格式将 ACTED_IN 关系及相关节点导出到 export-cypher-format-updateAll.cypher
MATCH (person)-[r:ACTED_IN]->(movie)
WITH collect(DISTINCT person) + collect(DISTINCT movie) AS importNodes, collect(r) AS importRels
CALL apoc.export.cypher.data(importNodes, importRels,
"export-cypher-format-updateAll.cypher",
{ format: "plain", cypherFormat: "updateAll" })
YIELD file, batches, source, format, nodes, relationships, properties, time, rows, batchSize
RETURN file, batches, source, format, nodes, relationships, properties, time, rows, batchSize;
| file | batches | source | format | 节点 | relationships | 属性 | time | rows | batchSize |
|---|---|---|---|---|---|---|---|---|---|
"export-cypher-format-updateAll.cypher" |
1 |
"data: nodes(5), rels(4)" |
"cypher" |
5 |
4 |
15 |
8 |
9 |
20000 |
CREATE CONSTRAINT uniqueConstraint FOR (node:`UNIQUE IMPORT LABEL`) REQUIRE (node.`UNIQUE IMPORT ID`) IS UNIQUE;
UNWIND [{_id:0, properties:{tagline:"Welcome to the Real World", title:"The Matrix", released:1999}}] AS row
MERGE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Movie;
UNWIND [{_id:80, properties:{born:1960, name:"Hugo Weaving"}},
{_id:7, properties:{born:1967, name:"Carrie-Anne Moss"}},
{_id:44, properties:{born:1961, name:"Laurence Fishburne"}},
{_id:27, properties:{born:1964, name:"Keanu Reeves"}}] AS row
MERGE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Person;
UNWIND [{start: {_id:27}, end: {_id:0}, properties:{roles:["Neo"]}},
{start: {_id:7}, end: {_id:0}, properties:{roles:["Trinity"]}},
{start: {_id:44}, end: {_id:0}, properties:{roles:["Morpheus"]}},
{start: {_id:80}, end: {_id:0}, properties:{roles:["Agent Smith"]}}] AS row
MATCH (start:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.start._id})
MATCH (end:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.end._id})
MERGE (start)-[r:ACTED_IN]->(end) SET r += row.properties;
MATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 20000 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;
DROP CONSTRAINT uniqueConstraint;
如果我们已经在目标数据库中拥有这些节点,可以使用 cypherFormat: "addStructure" 仅为关系创建 Cypher CREATE 语句。
以下示例使用 addStructure 格式将 ACTED_IN 关系及相关节点导出到 export-cypher-format-addStructure.cypher
MATCH (person)-[r:ACTED_IN]->(movie)
WITH collect(DISTINCT person) + collect(DISTINCT movie) AS importNodes, collect(r) AS importRels
CALL apoc.export.cypher.data(importNodes, importRels,
"export-cypher-format-addStructure.cypher",
{ format: "plain", cypherFormat: "addStructure" })
YIELD file, batches, source, format, nodes, relationships, properties, time, rows, batchSize
RETURN file, batches, source, format, nodes, relationships, properties, time, rows, batchSize;
| file | batches | source | format | 节点 | relationships | 属性 | time | rows | batchSize |
|---|---|---|---|---|---|---|---|---|---|
"export-cypher-format-addStructure.cypher" |
1 |
"data: nodes(5), rels(4)" |
"cypher" |
5 |
4 |
15 |
4 |
9 |
20000 |
UNWIND [{_id:0, properties:{tagline:"Welcome to the Real World", title:"The Matrix", released:1999}}] AS row
MERGE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) ON CREATE SET n += row.properties SET n:Movie;
UNWIND [{_id:7, properties:{born:1967, name:"Carrie-Anne Moss"}},
{_id:27, properties:{born:1964, name:"Keanu Reeves"}},
{_id:80, properties:{born:1960, name:"Hugo Weaving"}},
{_id:44, properties:{born:1961, name:"Laurence Fishburne"}}] AS row
MERGE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) ON CREATE SET n += row.properties SET n:Person;
UNWIND [{start: {_id:27}, end: {_id:0}, properties:{roles:["Neo"]}},
{start: {_id:7}, end: {_id:0}, properties:{roles:["Trinity"]}},
{start: {_id:44}, end: {_id:0}, properties:{roles:["Morpheus"]}},
{start: {_id:80}, end: {_id:0}, properties:{roles:["Agent Smith"]}}] AS row
MATCH (start:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.start._id})
MATCH (end:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.end._id})
CREATE (start)-[r:ACTED_IN]->(end) SET r += row.properties;
在此示例中,我们使用 MERGE 子句来创建尚不存在的节点,并且仅在节点不存在时才创建属性。在此例中,关系在目标数据库中尚不存在,因此需要创建它们。
如果这些关系已经存在但有需要更新的属性,我们可以使用 cypherFormat: "updateStructure" 来创建导入脚本。
以下示例使用 updateStructure 格式将 ACTED_IN 关系及相关节点导出到 export-cypher-format-updateStructure.cypher
MATCH (person)-[r:ACTED_IN]->(movie)
WITH collect(DISTINCT person) + collect(DISTINCT movie) AS importNodes, collect(r) AS importRels
CALL apoc.export.cypher.data(importNodes, importRels,
"export-cypher-format-updateStructure.cypher",
{ format: "plain", cypherFormat: "updateStructure" })
YIELD file, batches, source, format, nodes, relationships, properties, time, rows, batchSize
RETURN file, batches, source, format, nodes, relationships, properties, time, rows, batchSize;
| file | batches | source | format | 节点 | relationships | 属性 | time | rows | batchSize |
|---|---|---|---|---|---|---|---|---|---|
"export-cypher-format-updateStructure.cypher" |
1 |
"data: nodes(5), rels(4)" |
"cypher" |
0 |
4 |
4 |
2 |
4 |
20000 |
UNWIND [{start: {_id:27}, end: {_id:0}, properties:{roles:["Neo"]}},
{start: {_id:7}, end: {_id:0}, properties:{roles:["Trinity"]}},
{start: {_id:44}, end: {_id:0}, properties:{roles:["Morpheus"]}},
{start: {_id:80}, end: {_id:0}, properties:{roles:["Agent Smith"]}}] AS row
MATCH (start:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.start._id})
MATCH (end:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.end._id})
MERGE (start)-[r:ACTED_IN]->(end) SET r += row.properties;