apoc.export.cypher.query

此过程不建议在多线程中运行,因此并行运行时(Parallel runtime)不支持该过程。有关更多信息,请参阅 Cypher 手册 → 并行运行时

详细信息

语法

apoc.export.cypher.query(statement [, file, config ]) :: (file, batches, source, format, nodes, relationships, properties, time, rows, batchSize, cypherStatements, nodeStatements, relationshipStatements, schemaStatements, cleanupStatements)

描述

将给定 Cypher 查询的结果(包含索引)中的 NODERELATIONSHIP 值导出为 Cypher 语句并保存到指定文件(默认:Cypher Shell)。

输入参数

名称

类型

描述

statement

STRING

用于收集导出数据的查询语句。

file

STRING

数据导出到的文件名。默认值为:``。

config

MAP

{ stream = false :: BOOLEAN, batchSize = 20000 :: INTEGER, bulkImport = false :: BOOLEAN, timeoutSeconds = 100 :: INTEGER, compression = 'None' :: STRING, charset = 'UTF_8' :: STRING, sampling = false :: BOOLEAN, samplingConfig :: MAP }。默认值为:{}

返回参数

名称

类型

描述

file

STRING

数据导出到的文件名。

batches

INTEGER(整数)

导出过程执行的批次数。

source

STRING

导出数据的摘要。

format

STRING

文件的导出格式。

节点

INTEGER(整数)

已导出节点的数量。

relationships

INTEGER(整数)

已导出关系的数量。

属性

INTEGER(整数)

已导出属性的数量。

time

INTEGER(整数)

导出所花费的时间。

rows

INTEGER(整数)

返回的行数。

batchSize

INTEGER(整数)

导出过程执行的批处理大小。

cypherStatements

ANY

已执行的 Cypher 语句。

nodeStatements

ANY

已执行的节点语句。

relationshipStatements

ANY

已执行的关系语句。

schemaStatements

ANY

已执行的模式(Schema)语句。

cleanupStatements

ANY

已执行的清理语句。

配置参数

该过程支持以下配置参数

配置参数
名称 类型 默认 描述

writeNodeProperties

`BOOLEAN

false

如果为 true,则也导出属性。

stream

`BOOLEAN

false

将 json 直接流式传输到客户端的 data 字段中

format

STRING

cypher-shell

导出格式。支持以下值:

  • cypher-shell - 用于通过 Cypher Shell 导入

  • neo4j-shell - 用于通过 Neo4j Shell 导入

  • plain - 导出纯 Cypher,不含 begincommitawait 命令。用于通过 Neo4j Browser 导入

cypherFormat

STRING

create

Cypher 更新操作类型。支持以下值:

  • create - 仅使用 CREATE 子句

  • updateAll - 使用 MERGE 代替 CREATE

  • addStructure - 对节点使用 MATCH,对关系使用 MERGE

  • updateStructure - 对节点和关系均使用 MERGEMATCH

useOptimizations

MAP

{type: "UNWIND_BATCH", unwindBatchSize: 20}

用于生成 Cypher 语句的优化配置。type 支持以下值:

  • NONE - 使用 CREATE 语句导出文件

  • UNWIND_BATCH - 通过 UNWIND 方法批量导出实体,详情请参考 Michael Hunger 关于快速批量写入的文章。

  • UNWIND_BATCH_PARAMS - 与 UNWIND_BATCH 类似,但在适当的情况下也会使用参数

awaitForIndexes

INTEGER(整数)

300

当使用 format: "cypher-shell" 时,用于 db.awaitIndexes 的超时时间

ifNotExists

布尔值 (BOOLEAN)

false

如果为 true,则在约束和索引中添加 IF NOT EXISTS 关键字。

导出到文件

默认情况下,导出到文件系统是被禁用的。我们可以通过在 apoc.conf 中设置以下属性来启用它:

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 {stream:true} config and null as a 'file' parameter to stream the export back to your client.

导出文件被写入 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.conf
apoc.import.file.use_neo4j_config=false

Neo4j 现在将能够写入文件系统上的任何位置,因此在设置此属性之前,请确保这是您的意图。

导出流

如果我们不想导出到文件,可以通过将文件名设置为 null 并提供 stream:true 配置,将结果流式传输回 data 列。

使用示例

本节中的示例基于以下示例图

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 可视化显示了导入的图

play movies
图 1. 电影图谱可视化

导出流

以下查询演示了如何使用 apoc.export.cypher.query 导出流

查询
CALL apoc.export.cypher.query(
 "MATCH ()-[r]->()
 RETURN *",
 null,
 { format: "cypher-shell", stream: true })
结果
file batches source format 节点 relationships 属性 time rows batchSize cypherStatements

null

1

"statement: nodes(8), rels(7)"

"cypher"

8

7

21

1

15

2000

":begin CREATE CONSTRAINT UNIQUE_IMPORT_NAME FOR (node:`UNIQUE IMPORT LABEL`) REQUIRE (node.UNIQUE IMPORT ID) IS UNIQUE; :commit :begin UNWIND [{_id:13, 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:17, properties:{born:1960, name:"Hugo Weaving"}}, {_id:16, properties:{born:1961, name:"Laurence Fishburne"}}, {_id:14, properties:{born:1964, name:"Keanu Reeves"}}, {_id:15, properties:{born:1967, name:"Carrie-Anne Moss"}}, {_id:19, properties:{born:1965, name:"Lana Wachowski"}}, {_id:18, properties:{born:1967, name:"Lilly Wachowski"}}, {_id:20, properties:{born:1952, name:"Joel Silver"}}] AS row CREATE (n:`UNIQUE IMPORT LABEL`{UNIQUE IMPORT ID: row._id}) SET n += row.properties SET n:Person; :commit :begin UNWIND [{start: {_id:15}, end: {_id:13}, properties:{roles:["Trinity"]}}, {start: {_id:14}, end: {_id:13}, properties:{roles:["Neo"]}}, {start: {_id:17}, end: {_id:13}, properties:{roles:["Agent Smith"]}}, {start: {_id:16}, end: {_id:13}, properties:{roles:["Morpheus"]}}] 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; UNWIND [{start: {_id:20}, end: {_id:13}, properties:{}}] 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:PRODUCED]→(end) SET r += row.properties; UNWIND [{start: {_id:18}, end: {_id:13}, properties:{}}, {start: {_id:19}, end: {_id:13}, properties:{}}] 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:DIRECTED]→(end) SET r += row.properties; :commit :begin MATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 20000 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.UNIQUE IMPORT ID; :commit :begin DROP CONSTRAINT UNIQUE_IMPORT_NAME; :commit "

导出到文件

Cypher 导出过程均支持写入多个文件或多个列。我们可以通过传入配置 separateFiles: true 来启用此模式

以下查询将所有 ACTED_IN 关系及对应的节点导出到以 actedIn 为前缀的文件中

CALL apoc.export.cypher.query(
  "MATCH ()-[r:ACTED_IN]->()
   RETURN *",
  "actedIn.cypher",
  { format: "cypher-shell", separateFiles: true })
YIELD file, batches, source, format, nodes, relationships, time, rows, batchSize
RETURN file, batches, source, format, nodes, relationships, time, rows, batchSize;
结果
file batches source format 节点 relationships time rows batchSize

"actedIn.cypher"

1

"statement: nodes(10), rels(8)"

"cypher"

10

8

3

18

20000

这将创建以下文件

结果
名称 字节大小 行数

actedIn.cleanup.cypher

234

6

actedIn.nodes.cypher

893

6

actedIn.relationships.cypher

757

6

actedIn.schema.cypher

109

3

上述每个文件都包含了图的一部分。让我们看看它们的内容

actedIn.cleanup.cypher
:begin
MATCH (n:`UNIQUE IMPORT LABEL`)  WITH n LIMIT 20000 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;
:commit
:begin
DROP CONSTRAINT uniqueConstraint;
:commit
actedIn.nodes.cypher
:begin
UNWIND [{_id:28, properties:{tagline:"Welcome to the Real World", title:"The Matrix", released:1999}}, {_id:37, 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:31, properties:{born:1961, name:"Laurence Fishburne"}}, {_id:30, properties:{born:1967, name:"Carrie-Anne Moss"}}, {_id:42, properties:{born:1964, name:"Keanu Reeves"}}, {_id:0, properties:{born:1960, name:"Hugo Weaving"}}, {_id:29, properties:{born:1964, name:"Keanu Reeves"}}, {_id:38, properties:{born:1960, name:"Hugo Weaving"}}, {_id:43, properties:{born:1967, name:"Carrie-Anne Moss"}}, {_id:57, 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;
:commit
actedIn.relationships.cypher
:begin
UNWIND [{start: {_id:31}, end: {_id:28}, properties:{roles:["Morpheus"]}}, {start: {_id:42}, end: {_id:37}, properties:{roles:["Neo"]}}, {start: {_id:38}, end: {_id:37}, properties:{roles:["Agent Smith"]}}, {start: {_id:0}, end: {_id:28}, properties:{roles:["Agent Smith"]}}, {start: {_id:29}, end: {_id:28}, properties:{roles:["Neo"]}}, {start: {_id:43}, end: {_id:37}, properties:{roles:["Trinity"]}}, {start: {_id:30}, end: {_id:28}, properties:{roles:["Trinity"]}}, {start: {_id:57}, end: {_id:37}, properties:{roles:["Morpheus"]}}] 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;
:commit
actedIn.schema.cypher
:begin
CREATE CONSTRAINT uniqueConstraint FOR (node:`UNIQUE IMPORT LABEL`) REQUIRE (node.`UNIQUE IMPORT ID`) IS UNIQUE;
:commit

之后,我们可以将这些文件应用到目标 Neo4j 实例中,既可以通过将内容流式传输到 Cypher Shell,也可以使用 运行 Cypher 片段 中描述的过程。

在返回导出语句流时,我们也可以使用 separateFiles。结果将显示在名为 nodeStatementsrelationshipStatementscleanupStatementsschemaStatements 的列中,而不是 cypherStatements 中。

以下查询返回所有 ACTED_IN 关系及对应节点的流

CALL apoc.export.cypher.query(
  "MATCH ()-[r:ACTED_IN]->()
   RETURN *",
  null,
  { format: "cypher-shell", separateFiles: true })
YIELD nodes, relationships, properties, nodeStatements, relationshipStatements, cleanupStatements, schemaStatements
RETURN nodes, relationships, properties, nodeStatements, relationshipStatements, cleanupStatements, schemaStatements;
结果
节点 relationships 属性 nodeStatements relationshipStatements cleanupStatements schemaStatements

10

8

30

":begin UNWIND [{_id:28, properties:{tagline:\"Welcome to the Real World\", title:\"The Matrix\", released:1999}}, {_id:37, 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:0, properties:{born:1960, name:\"Hugo Weaving\"}}, {_id:42, properties:{born:1964, name:\"Keanu Reeves\"}}, {_id:31, properties:{born:1961, name:\"Laurence Fishburne\"}}, {_id:29, properties:{born:1964, name:\"Keanu Reeves\"}}, {_id:30, properties:{born:1967, name:\"Carrie-Anne Moss\"}}, {_id:43, properties:{born:1967, name:\"Carrie-Anne Moss\"}}, {_id:38, properties:{born:1960, name:\"Hugo Weaving\"}}, {_id:57, 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; :commit "

":begin UNWIND [{start: {_id:31}, end: {_id:28}, properties:{roles:[\"Morpheus\"]}}, {start: {_id:38}, end: {_id:37}, properties:{roles:[\"Agent Smith\"]}}, {start: {_id:0}, end: {_id:28}, properties:{roles:[\"Agent Smith\"]}}, {start: {_id:30}, end: {_id:28}, properties:{roles:[\"Trinity\"]}}, {start: {_id:29}, end: {_id:28}, properties:{roles:[\"Neo\"]}}, {start: {_id:43}, end: {_id:37}, properties:{roles:[\"Trinity\"]}}, {start: {_id:42}, end: {_id:37}, properties:{roles:[\"Neo\"]}}, {start: {_id:57}, end: {_id:37}, properties:{roles:[\"Morpheus\"]}}] 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; :commit "

":begin MATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 20000 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.UNIQUE IMPORT ID; :commit :begin DROP CONSTRAINT uniqueConstraint; :commit "

":begin CREATE CONSTRAINT uniqueConstraint FOR (node:`UNIQUE IMPORT LABEL`) REQUIRE (node.UNIQUE IMPORT ID) IS UNIQUE; :commit "

之后,我们可以将每一列的内容(不包括双引号)复制并粘贴到 Cypher Shell 会话中,或者保存到本地文件中并流式传输到 Cypher Shell 会话中。如果我们希望导出的 Cypher 语句能够粘贴到 Neo4j Browser 查询编辑器中,则需要使用配置 format: "plain"

© . This site is unofficial and not affiliated with Neo4j, Inc.