导出到 GraphML
GraphML 导出过程将数据导出为 Gephi 和 CytoScape 等其他工具用于读取图数据的格式。
GraphML 不支持属性图数据模型的全部灵活性。主要有两个限制:
-
GraphML 假定所有具有相同属性名称的节点或关系属性都具有相同类型的属性值。Neo4j 允许每个属性名称具有混合类型。如果属性名称具有混合值类型,则其值将导出为
STRING
。 -
GraphML 支持的值类型比 Neo4j 少。因此,所有
POINT
和时间值都将格式化为STRING
导出。例如
三维点
{"crs":"wgs-84-3d","latitude":56.7,"longitude":12.78,"height":100.0}
二维点
{"crs":"wgs-84-3d","latitude":56.7,"longitude":12.78,"height":null}
日期
2018-10-10
LocalDateTime
2018-10-10T00:00
请注意,为了正确执行点序列化,不建议导出具有坐标 x、y 和 crs: 'wgs-84' 的点,例如
point({x: 56.7, y: 12.78, crs: 'wgs-84'})
。否则,该点将导出为经度和纬度(以及高度),而不是 x 和 y(以及 z)。
可用存储过程
下表描述了可用的存储过程
限定名称 | 类型 |
---|---|
apoc.export.graphml.all |
|
apoc.export.graphml.data |
|
apoc.export.graphml.graph |
|
apoc.export.graphml.query |
|
导出的标签按字母顺序排列。labels()
函数的输出未排序,请结合 apoc.coll.sort()
使用。
导出到文件
默认情况下,文件系统导出已禁用。我们可以通过在 apoc.conf
中设置以下属性来启用它
apoc.export.file.enabled=true
有关访问 apoc.conf
的更多信息,请参阅配置选项章节。
如果我们在未首先设置此属性的情况下尝试使用任何导出存储过程,将收到以下错误消息
无法调用存储过程:原因:java.lang.RuntimeException: 未启用文件导出,请在您的 |
导出文件写入 import
目录,该目录由 server.directories.import
属性定义。这意味着我们提供的任何文件路径都是相对于此目录的。如果尝试写入绝对路径,例如 /tmp/filename
,将收到类似于以下内容的错误消息
无法调用存储过程:原因:java.io.FileNotFoundException: /path/to/neo4j/import/tmp/fileName (无此文件或目录) |
我们可以通过在 apoc.conf
中设置以下属性来启用向文件系统上任意位置的写入
apoc.import.file.use_neo4j_config=false
Neo4j 现在将能够写入文件系统上的任意位置,因此在设置此属性之前请务必确认这是您的意图。 |
示例
本节包含如何使用导出到 Cypher 存储过程的示例。这些示例基于电影数据集,可以通过运行以下 Cypher 查询导入
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 可视化显示了导入的图

往返分离的 GraphML 文件
使用此数据集
CREATE (f:Foo:Foo2:Foo0 {name:'foo', born:Date('2018-10-10'), place:point({ longitude: 56.7, latitude: 12.78, height: 100 })})-[:KNOWS]->(b:Bar {name:'bar',age:42, place:point({ longitude: 56.7, latitude: 12.78})});
CREATE (:Foo {name: 'zzz'})-[:KNOWS]->(:Bar {age: 0});
CREATE (:Foo {name: 'aaa'})-[:KNOWS {id: 1}]->(:Bar {age: 666});
我们可以执行这 3 个导出查询
// Foo nodes
call apoc.export.graphml.query('MATCH (start:Foo)-[:KNOWS]->(:Bar) RETURN start', 'queryNodesFoo.graphml', {useTypes: true});
// Bar nodes
call apoc.export.graphml.query('MATCH (:Foo)-[:KNOWS]->(end:Bar) RETURN end', 'queryNodesBar.graphml', {useTypes: true});
// KNOWS rels
MATCH (:Foo)-[rel:KNOWS]->(:Bar)
WITH collect(rel) as rels
call apoc.export.graphml.data([], rels, 'queryRelationship.graphml', {useTypes: true})
YIELD nodes, relationships RETURN nodes, relationships;
在这种情况下,我们将有这 3 个文件:.queryNodesFoo.graphml
<?xml version='1.0' encoding='UTF-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="born" for="node" attr.name="born" attr.type="string"/>
<key id="name" for="node" attr.name="name" attr.type="string"/>
<key id="place" for="node" attr.name="place" attr.type="string"/>
<key id="labels" for="node" attr.name="labels" attr.type="string"/>
<graph id="G" edgedefault="directed">
<node id="n0" labels=":Foo:Foo0:Foo2"><data key="labels">:Foo:Foo0:Foo2</data><data key="born">2018-10-10</data><data key="name">foo</data><data key="place">{"crs":"wgs-84-3d","latitude":12.78,"longitude":56.7,"height":100.0}</data></node>
<node id="n3" labels=":Foo"><data key="labels">:Foo</data><data key="name">zzz</data></node>
<node id="n5" labels=":Foo"><data key="labels">:Foo</data><data key="name">aaa</data></node>
</graph>
</graphml>
<?xml version='1.0' encoding='UTF-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="name" for="node" attr.name="name" attr.type="string"/>
<key id="place" for="node" attr.name="place" attr.type="string"/>
<key id="age" for="node" attr.name="age" attr.type="long"/>
<key id="labels" for="node" attr.name="labels" attr.type="string"/>
<graph id="G" edgedefault="directed">
<node id="n1" labels=":Bar"><data key="labels">:Bar</data><data key="name">bar</data><data key="age">42</data><data key="place">{"crs":"wgs-84","latitude":12.78,"longitude":56.7,"height":null}</data></node>
<node id="n4" labels=":Bar"><data key="labels">:Bar</data><data key="age">0</data></node>
<node id="n6" labels=":Bar"><data key="labels">:Bar</data><data key="age">666</data></node>
</graph>
</graphml>
<?xml version='1.0' encoding='UTF-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="label" for="edge" attr.name="label" attr.type="string"/>
<key id="id" for="edge" attr.name="id" attr.type="long"/>
<graph id="G" edgedefault="directed">
<edge id="e0" source="n0" target="n1" label="KNOWS"><data key="label">KNOWS</data></edge>
<edge id="e1" source="n3" target="n4" label="KNOWS"><data key="label">KNOWS</data></edge>
<edge id="e2" source="n5" target="n6" label="KNOWS"><data key="label">KNOWS</data><data key="id">1</data></edge>
</graph>
</graphml>
因此,我们可以用这种方式在另一个数据库中导入,以使用这些查询重新创建原始数据集
CALL apoc.import.graphml('queryNodesFoo.graphml', {readLabels: true, storeNodeIds: true});
CALL apoc.import.graphml('queryNodesBar.graphml', {readLabels: true, storeNodeIds: true});
CALL apoc.import.graphml('queryRelationship.graphml', {readLabels: true, source: {label: 'Foo'}, target: {label: 'Bar'}});
请注意,我们必须先执行节点导入,并且我们使用 useTypes: true
将 node
标签的 id
属性作为属性导入,并使用 readLabels
用标签填充节点。
使用自定义属性键
否则,我们可以利用自定义属性,并以这种方式避免导入 id
属性(通过 useTypes:true
)(与之前相同的数据集和节点导出查询)
// KNOWS rels
MATCH (:Foo)-[rel:KNOWS]->(:Bar)
WITH collect(rel) as rels
call apoc.export.graphml.data([], rels, 'queryRelationship.graphml',
{useTypes: true, source: {id: 'name'}, label: {id: 'age'}})
YIELD nodes, relationships RETURN nodes, relationships;
强烈建议使用唯一性约束来确保唯一性,因此在这种情况下,对于标签 Foo
及其属性 name
,以及对于标签 Bar
及其属性 age
。
上述查询生成此关系文件
<?xml version='1.0' encoding='UTF-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="label" for="edge" attr.name="label" attr.type="string"/>
<key id="id" for="edge" attr.name="id" attr.type="long"/>
<graph id="G" edgedefault="directed">
<edge id="e0" source="foo" sourceType="string" target="42" targetType="long" label="KNOWS"><data key="label">KNOWS</data></edge>
<edge id="e1" source="zzz" sourceType="string" target="0" targetType="long" label="KNOWS"><data key="label">KNOWS</data></edge>
<edge id="e2" source="aaa" sourceType="string" target="666" targetType="long" label="KNOWS"><data key="label">KNOWS</data><data key="id">1</data></edge>
</graph>
</graphml>
最后,我们可以使用与上述相同的 ID(名称和年龄)导入文件
CALL apoc.import.graphml('queryNodesFoo.graphml', {readLabels: true});
CALL apoc.import.graphml('queryNodesBar.graphml', {readLabels: true});
CALL apoc.import.graphml('queryRelationship.graphml',
{readLabels: true, source: {label: 'Foo', id: 'name'}, target: {label: 'Bar', id: 'age'}});
导出整个数据库到 GraphML
apoc.export.graphml.all
存储过程将整个数据库导出到 GraphML 文件或作为流。
movies.graphml
文件CALL apoc.export.graphml.all("movies.graphml", {})
文件 | 源 | 格式 | 节点数 | 关系数 | 属性数 | 时间 | 行数 | 批处理大小 | 批次数 | 完成 | 数据 |
---|---|---|---|---|---|---|---|---|---|---|---|
"movies.graphml" |
"数据库:节点(8),关系(7)" |
"graphml" |
8 |
7 |
21 |
4 |
15 |
-1 |
0 |
是 |
NULL |
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="born" for="node" attr.name="born"/>
<key id="name" for="node" attr.name="name"/>
<key id="tagline" for="node" attr.name="tagline"/>
<key id="label" for="node" attr.name="label"/>
<key id="title" for="node" attr.name="title"/>
<key id="released" for="node" attr.name="released"/>
<key id="roles" for="edge" attr.name="roles"/>
<key id="label" for="edge" attr.name="label"/>
<graph id="G" edgedefault="directed">
<node id="n188" labels=":Movie"><data key="labels">:Movie</data><data key="title">The Matrix</data><data key="tagline">Welcome to the Real World</data><data key="released">1999</data></node>
<node id="n189" labels=":Person"><data key="labels">:Person</data><data key="born">1964</data><data key="name">Keanu Reeves</data></node>
<node id="n190" labels=":Person"><data key="labels">:Person</data><data key="born">1967</data><data key="name">Carrie-Anne Moss</data></node>
<node id="n191" labels=":Person"><data key="labels">:Person</data><data key="born">1961</data><data key="name">Laurence Fishburne</data></node>
<node id="n192" labels=":Person"><data key="labels">:Person</data><data key="born">1960</data><data key="name">Hugo Weaving</data></node>
<node id="n193" labels=":Person"><data key="labels">:Person</data><data key="born">1967</data><data key="name">Lilly Wachowski</data></node>
<node id="n194" labels=":Person"><data key="labels">:Person</data><data key="born">1965</data><data key="name">Lana Wachowski</data></node>
<node id="n195" labels=":Person"><data key="labels">:Person</data><data key="born">1952</data><data key="name">Joel Silver</data></node>
<edge id="e267" source="n189" target="n188" label="ACTED_IN"><data key="label">ACTED_IN</data><data key="roles">["Neo"]</data></edge>
<edge id="e268" source="n190" target="n188" label="ACTED_IN"><data key="label">ACTED_IN</data><data key="roles">["Trinity"]</data></edge>
<edge id="e269" source="n191" target="n188" label="ACTED_IN"><data key="label">ACTED_IN</data><data key="roles">["Morpheus"]</data></edge>
<edge id="e270" source="n192" target="n188" label="ACTED_IN"><data key="label">ACTED_IN</data><data key="roles">["Agent Smith"]</data></edge>
<edge id="e271" source="n193" target="n188" label="DIRECTED"><data key="label">DIRECTED</data></edge>
<edge id="e272" source="n194" target="n188" label="DIRECTED"><data key="label">DIRECTED</data></edge>
<edge id="e273" source="n195" target="n188" label="PRODUCED"><data key="label">PRODUCED</data></edge>
</graph>
</graphml>
data
列中返回整个数据库CALL apoc.export.graphml.all(null, {stream:true})
YIELD file, nodes, relationships, properties, data
RETURN file, nodes, relationships, properties, data;
文件 | 节点数 | 关系数 | 属性数 | 数据 |
---|---|---|---|---|
|
|
|
|
|
导出指定的节点和关系到 GraphML
apoc.export.graphml.data
存储过程将指定的节点和关系导出到 CSV 文件或作为流。
:Person
标签且 name
属性以 L
开头的节点导出到 movies-l.csv
文件MATCH (person:Person)
WHERE person.name STARTS WITH "L"
WITH collect(person) AS people
CALL apoc.export.graphml.data(people, [], "movies-l.graphml", {})
YIELD file, source, format, nodes, relationships, properties, time, rows, batchSize, batches, done, data
RETURN file, source, format, nodes, relationships, properties, time, rows, batchSize, batches, done, data
文件 | 源 | 格式 | 节点数 | 关系数 | 属性数 | 时间 | 行数 | 批处理大小 | 批次数 | 完成 | 数据 |
---|---|---|---|---|---|---|---|---|---|---|---|
"movies-l.csv" |
"数据:节点(3),关系(0)" |
"csv" |
3 |
0 |
6 |
2 |
3 |
20000 |
1 |
是 |
NULL |
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="born" for="node" attr.name="born"/>
<key id="name" for="node" attr.name="name"/>
<key id="label" for="node" attr.name="label"/>
<graph id="G" edgedefault="directed">
<node id="n191" labels=":Person"><data key="labels">:Person</data><data key="born">1961</data><data key="name">Laurence Fishburne</data></node>
<node id="n193" labels=":Person"><data key="labels">:Person</data><data key="born">1967</data><data key="name">Lilly Wachowski</data></node>
<node id="n194" labels=":Person"><data key="labels">:Person</data><data key="born">1965</data><data key="name">Lana Wachowski</data></node>
</graph>
</graphml>
data
列中返回所有 ACTED_IN
关系以及该关系两端的带有 Person
和 Movie
标签的节点MATCH (person:Person)-[actedIn:ACTED_IN]->(movie:Movie)
WITH collect(DISTINCT person) AS people, collect(DISTINCT movie) AS movies, collect(actedIn) AS actedInRels
CALL apoc.export.graphml.data(people + movies, actedInRels, null, {stream: true})
YIELD file, nodes, relationships, properties, data
RETURN file, nodes, relationships, properties, data;
文件 | 节点数 | 关系数 | 属性数 | 数据 |
---|---|---|---|---|
|
|
|
|
|
导出 Cypher 查询结果到 GraphML
apoc.export.graphml.query
存储过程将 Cypher 查询结果导出到 CSV 文件或作为流。
DIRECTED
关系以及该关系两端的带有 Person
和 Movie
标签的节点导出到 movies-directed.graphml
文件WITH "MATCH path = (person:Person)-[directed:DIRECTED]->(movie)
RETURN person, directed, movie" AS query
CALL apoc.export.graphml.query(query, "movies-directed.graphml", {})
YIELD file, source, format, nodes, relationships, properties, time, rows, batchSize, batches, done, data
RETURN file, source, format, nodes, relationships, properties, time, rows, batchSize, batches, done, data;
文件 | 源 | 格式 | 节点数 | 关系数 | 属性数 | 时间 | 行数 | 批处理大小 | 批次数 | 完成 | 数据 |
---|---|---|---|---|---|---|---|---|---|---|---|
"movies-directed.graphml" |
"语句:节点(3),关系(2)" |
"graphml" |
3 |
2 |
7 |
2 |
5 |
-1 |
0 |
是 |
NULL |
movies-directed.csv
的内容如下所示
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="born" for="node" attr.name="born"/>
<key id="name" for="node" attr.name="name"/>
<key id="tagline" for="node" attr.name="tagline"/>
<key id="label" for="node" attr.name="label"/>
<key id="title" for="node" attr.name="title"/>
<key id="released" for="node" attr.name="released"/>
<key id="label" for="edge" attr.name="label"/>
<graph id="G" edgedefault="directed">
<node id="n188" labels=":Movie"><data key="labels">:Movie</data><data key="title">The Matrix</data><data key="tagline">Welcome to the Real World</data><data key="released">1999</data></node>
<node id="n193" labels=":Person"><data key="labels">:Person</data><data key="born">1967</data><data key="name">Lilly Wachowski</data></node>
<node id="n194" labels=":Person"><data key="labels">:Person</data><data key="born">1965</data><data key="name">Lana Wachowski</data></node>
<edge id="e271" source="n193" target="n188" label="DIRECTED"><data key="label">DIRECTED</data></edge>
<edge id="e272" source="n194" target="n188" label="DIRECTED"><data key="label">DIRECTED</data></edge>
</graph>
</graphml>
DIRECTED
关系以及该关系两端的带有 Person
和 Movie
标签的节点WITH "MATCH path = (person:Person)-[directed:DIRECTED]->(movie)
RETURN person, directed, movie" AS query
CALL apoc.export.graphml.query(query, null, {stream: true})
YIELD file, nodes, relationships, properties, data
RETURN file, nodes, relationships, properties, data;
文件 | 节点数 | 关系数 | 属性数 | 数据 |
---|---|---|---|---|
|
|
|
|
|
您也可以压缩要导出的文件。 点击此处查看更多信息 |