LOAD CSV

LOAD CSV 用于将 CSV 文件中的数据导入 Neo4j 数据库。

LOAD CSV FROM 'https://data.neo4j.com/bands/artists.csv' (1)
AS row  (2)
MERGE (:Artist {name: row[1], year: toInteger(row[2])})  (3)
1 FROM 获取包含 CSV 文件路径的 STRING
2 该子句一次解析一行,并将当前行临时存储在使用 AS 指定的变量中。
3 MERGE 子句访问 row 变量以将数据插入数据库。

LOAD CSV 支持本地和远程 URL。本地路径相对于 Neo4j 安装文件夹解析。

加载 CSV 文件需要 加载权限

将 CSV 数据导入 Neo4j

导入本地文件

您可以将 CSV 文件存储在数据库服务器上,然后通过使用 file:/// URL 访问它们。默认情况下,路径相对于 Neo4j 导入目录解析。

示例 1. 从本地文件导入艺术家姓名和年份信息
artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'file:///artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

有关将数据导入 Aura 实例的方法,请参阅 Aura → 导入数据
使用 file:/// URL 时,空格和其他非字母数字字符必须进行 URL 编码

文件 URL 的配置设置

dbms.security.allow_csv_import_from_file_urls

此设置确定是否允许 file:/// URL。

server.directories.import

此设置设置相对于其解析 file:/// URL 的根目录。

从远程位置导入

您可以从托管在远程路径上的 CSV 文件导入数据。

LOAD CSV 支持通过 HTTPS、HTTP 和 FTP(有或无凭据)访问 CSV 文件。它还遵循重定向,但那些更改协议的重定向除外(出于安全原因)。

强烈建议仅允许通过 HTTPS 等安全协议加载资源,而不是 HTTP 等不安全协议。这可以通过将 加载权限 限制为仅使用安全协议的可信来源来实现。如果绝对无法避免允许不安全协议,则 Neo4j 会在内部采取措施,在自身限制范围内增强这些请求的安全性。但是,这意味着虚拟主机上的不安全 URL 将无法正常工作,除非您将 JVM 参数 -Dsun.net.http.allowRestrictedHeaders=true 添加到配置设置 server.jvm.additional 中。

示例 2. 通过 HTTPS 从远程文件导入艺术家姓名和年份信息
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'https://data.neo4j.com/bands/artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

示例 3. 使用凭据通过 FTP 从远程文件导入艺术家姓名和年份信息
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'ftp://<username>:<password>@<domain>/bands/artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

从云 URI 导入

您可以从许多不同的云存储中导入数据

有关如何设置对云存储的访问,请参阅 操作手册 → 从云存储加载转储

从 Azure 云存储 URI 导入

您可以从托管在 Azure 云存储 URI 中的 CSV 文件导入数据。

示例 4. 从 Azure 云存储 URI 导入艺术家姓名和年份信息
azb://azb-account/azb-container/artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'azb://azb-account/azb-container/artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

从 Google 云存储 URI 导入

您可以从托管在 Google 云存储 URI 中的 CSV 文件导入数据。

示例 5. 从 Google 云存储 URI 导入艺术家姓名和年份信息

gs://gs-bucket/artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'gs://gs-bucket/artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

从 AWS S3 URI 导入

您可以从 AWS S3 URI 中托管的 CSV 文件导入数据。

示例 6. 从 AWS S3 URI 导入艺术家姓名和年份信息
s3://aws-bucket/artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 's3://aws-bucket/artists.csv' AS row
MERGE (a:Artist {name: row[1], year: toInteger(row[2])})
RETURN a.name, a.year
结果
a.name a.year

'ABBA'

'1992'

'Roxette'

'1986'

'Europe'

'1979'

'The Cardigans'

'1992'

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

导入压缩的 CSV 文件

LOAD CSV 可以读取使用 ZIP 或 gzip 压缩的本地 CSV 文件。ZIP 存档可以具有任意目录结构,但可能仅包含一个 CSV 文件。

从 ZIP 文件中导入 CSV 文件
LOAD CSV FROM 'file:///artists.zip' AS row
MERGE (:Artist {name: row[1], year: toInteger(row[2])})
您无法从远程 URL 加载压缩的 CSV 文件。

从关系数据库导入数据

如果源数据来自关系模型,则值得评估如何从迁移到图数据模型中获得最大收益。在运行导入之前,请考虑如何将数据建模为图形,并在运行导入时相应地调整其结构(请参阅图数据建模)。

来自关系数据库的数据可能包含一个或多个 CSV 文件,具体取决于源数据库结构。一种高性能的方法是运行多次 LOAD CSV 以分别从关系中导入节点。

示例 7. 从单个 CSV 文件导入

源文件books.csv包含有关作者和书籍的信息。从图的角度来看,这些是具有不同标签的节点,因此加载它们需要不同的查询。

该示例对该文件执行多次 LOAD CSV,并且每次执行都专注于创建一个实体类型。

books.csv
id,title,author,publication_year,genre,rating,still_in_print,last_purchased
19515,The Heights,Anne Conrad,2012,Comedy,5,true,2023/4/12 8:17:00
39913,Starship Ghost,Michael Tyler,1985,Science Fiction|Horror,4.2,false,2022/01/16 17:15:56
60980,The Death Proxy,Tim Brown,2002,Horror,2.1,true,2023/11/26 8:34:26
18793,Chocolate Timeline,Mary R. Robb,1924,Romance,3.5,false,2022/9/17 14:23:45
67162,Stories of Three,Eleanor Link,2022,Romance|Comedy,2,true,2023/03/12 16:01:23
25987,Route Down Below,Tim Brown,2006,Horror,4.1,true,2023/09/24 15:34:18
查询
// Create `Book` nodes
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/books.csv' AS row
MERGE (b:Book {id: row.id, title: row.title})
MERGE (a:Author {name: row.author});

// Create `WROTE` relationships
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/books.csv' AS row
MATCH (a:Author{name: row.author})
MATCH (b:Book{id: row.id})
MERGE (a)-[:WROTE]->(b);
结果
Added 11 nodes, Set 17 properties, Added 11 labels
Created 6 relationships
示例 8. 从多个 CSV 文件导入

文件acted_in.csv包含有关演员与其出演的电影之间关系的数据(来自persons.csvmovies.csv)。演员和电影通过其 ID 列person_tmdbIdmovieId链接。

该文件还包含演员在电影中扮演的角色,并在 Neo4j 中作为关系属性导入。

acted_in.csv
movieId,person_tmdbId,role
1,12899,Slinky Dog (voice)
1,12898,Buzz Lightyear (voice)
...

导入此数据集需要三个LOAD CSV子句:前两个从persons.csv创建Person节点,从movies.csv创建Movie节点,第三个从acted_in.csv添加:ACTED_IN关系。

查询
// Create person nodes
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row
MERGE (p:Person {name: row.name, tmdbId: row.person_tmdbId});

// Create movie nodes
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row
MERGE (m:Movie {movieId: row.movieId, title: row.title});

// Create relationships
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/acted_in.csv' AS row
MATCH (p:Person {tmdbId: row.person_tmdbId})
MATCH (m:Movie {movieId: row.movieId})
MERGE (p)-[r:ACTED_IN {role: row.role}]->(m);
结果
Added 444 nodes, Set 888 properties, Added 444 labels
Added 93 nodes, Set 186 properties, Added 93 labels
Created 372 relationships, Set 372 properties
有关将 Northwind 数据集从 Postgres 导入到 Neo4j 的指南,请参阅入门指南中的教程:将数据从关系数据库导入 Neo4j

创建其他节点标签

在 Neo4j 中,一个节点可以有多个标签,而在关系设置中,混合实体并不那么简单。例如,Neo4j 中的节点可以同时标记为DogActor,而在关系模型中,狗和演员是单独的实体。

导入关系数据集后,可以添加更多标签,具体取决于用例。如果您在查询中使用其他标签,它们可以加快查找到节点的速度。

示例 9. 在Person节点上添加额外的Actor标签

来自acted_in.csv:ACTED_IN关系隐式地将演员定义为人员的子集。以下查询将一个额外的Actor标签添加到所有具有传出:ACTED_IN关系的人员。

查询
MATCH (p:Person)-[:ACTED_IN]->()
WITH DISTINCT p
SET p:Actor
结果
Added 353 labels

在导入期间预处理数据

将 CSV 列转换为 Neo4j 数据类型

LOAD CSV 将所有导入的 CSV 数据作为STRING属性插入。但是,Neo4j 支持一系列数据类型,并且使用适当的类型存储数据既可以更有效地查询它,又可以使用特定于类型的 Cypher® 函数处理它。

示例 10. 导入数字和时间数据

文件persons.csv中的person_tmdbIdborn列分别包含INTEGERDATE值。函数toInteger()date()允许在导入之前将这些值转换为适当的类型。

persons.csv
person_tmdbId,bio,born,bornIn,died,person_imdbId,name,person_poster,person_url
3,"Legendary Hollywood Icon Harrison Ford was born on July 13, 1942 in Chicago, Illinois.   His family history includes a strong lineage of actors, radio personalities, and models.   Harrison attended public high school in Park Ridge, Illinois where he was a member of the school Radio Station WMTH.  Harrison worked as the lead voice for sports reporting at WMTH for several years.   Acting wasn’t a major interest to Ford until his junior year at Ripon College when he first took an acting class...",1942-07-13,"Chicago, Illinois, USA",,148,Harrison Ford,https://image.tmdb.org/t/p/w440_and_h660_face/5M7oN3sznp99hWYQ9sX0xheswWX.jpg,https://themoviedb.org/person/3
...
查询
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row
MERGE (p:Person {tmdbId: toInteger(row.person_tmdbId)})
SET p.name = row.name, p.born = date(row.born)
RETURN
  p.name AS name,
  p.tmdbId AS tmdbId,
  p.born AS born
LIMIT 5
结果
name tmdbId born

'Harrison Ford'

3

1942-07-13

'Tom Hanks'

31

1956-07-09

'Robin Wright'

32

1966-04-08

'Sally Field'

35

1946-11-06

'Sean Bean'

48

1959-04-17

5 行

添加了 444 个节点,设置了 1332 个属性,添加了 444 个标签

有关类型转换函数的列表,请参阅转换数据值

处理null

Neo4j 不存储null值。CSV 文件中的null或空字段可以在LOAD CSV中跳过或替换为默认值。

示例 11. 处理包含null值的文件

在文件companies.csv中,某些行未为某些列指定值。这些示例显示了处理null值的几种选项。

companies.csv
Id,Name,Location,Email,BusinessType
1,Neo4j,San Mateo,[email protected],P
2,AAA,,[email protected],
3,BBB,Chicago, ,G
,CCC,Michigan,[email protected],G
跳过null
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
WITH row
WHERE row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})
null值提供默认值
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
WITH row
WHERE row.Id IS NOT NULL
MERGE (c:Company {id: row.Id, hqLocation: coalesce(row.Location, "Unknown")})
将空STRING值更改为null值(未存储)
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
WITH row
WHERE row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})
SET c.email = nullIf(trim(row.Email), "")
null值不会存储在数据库中。选择性地去除某些值的策略是将它们映射到null值。最后一个查询中的空STRING值用作示例。

拆分列表值

函数split()允许将元素的STRING转换为列表。

示例 12. 将电影语言和类型解析为列表

文件movies.csv包含标题行和总共 94 行。

languagesgenres列包含类似列表的值。两者都以管道|分隔,split()允许在将它们插入数据库之前将它们转换为 Cypher 列表。

movies.csv
movieId,title,budget,countries,movie_imdbId,imdbRating,imdbVotes,languages,plot,movie_poster,released,revenue,runtime,movie_tmdbId,movie_url,year,genres
1,Toy Story,30000000.0,USA,114709,8.3,591836,English,A cowboy doll is profoundly threatened and jealous when a new spaceman figure supplants him as top toy in a boy's room.,https://image.tmdb.org/t/p/w440_and_h660_face/uXDfjJbdP4ijW5hWSBrPrlKpxab.jpg,1995-11-22,373554033.0,81,862,https://themoviedb.org/movie/862,1995,Adventure|Animation|Children|Comedy|Fantasy
2,Jumanji,65000000.0,USA,113497,6.9,198355,English|French,"When two kids find and play a magical board game, they release a man trapped for decades in it and a host of dangers that can only be stopped by finishing the game.",https://image.tmdb.org/t/p/w440_and_h660_face/vgpXmVaVyUL7GGiDeiK1mKEKzcX.jpg,1995-12-15,262797249.0,104,8844,https://themoviedb.org/movie/8844,1995,Adventure|Children|Fantasy
...
查询
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row
MERGE (m:Movie {id: toInteger(row.movieId)})
SET
    m.title = row.title,
    m.imdbId = toInteger(row.movie_imdbId),
    m.languages = split(row.languages, '|'),
    m.genres = split(row.genres, '|')
RETURN
  m.title AS title,
  m.imdbId AS imdbId,
  m.languages AS languages,
  m.genres AS genres
LIMIT 5
结果
title imdbId languages genres

'Toy Story'

114709

['English']

['Adventure', 'Animation', 'Children', 'Comedy', 'Fantasy']

'Jumanji'

113497

['English', 'French']

['Adventure', 'Children', 'Fantasy']

'Grumpier Old Men'

113228

['English']

['Comedy', 'Romance"]

'Waiting to Exhale'

114885

['English']

['Comedy', 'Romance', 'Drama']

'Father of the Bride Part II'

113041

['English']

['Comedy']

5 行

添加了 93 个节点,设置了 465 个属性,添加了 93 个标签

有关更多STRING操作函数,请参阅字符串函数

建议

创建属性唯一性约束

始终在导入数据之前创建属性唯一性约束,以避免重复或冲突的实体。如果源文件包含重复数据并且正确的约束到位,则 Cypher 会引发错误。

示例 13. 在人员 ID 上创建节点属性唯一性约束
persons.csv
person_tmdbId,bio,born,bornIn,died,person_imdbId,name,person_poster,person_url
3,"Legendary Hollywood Icon Harrison Ford was born on July 13, 1942 in Chicago, Illinois.   His family history includes a strong lineage of actors, radio personalities, and models.   Harrison attended public high school in Park Ridge, Illinois where he was a member of the school Radio Station WMTH.  Harrison worked as the lead voice for sports reporting at WMTH for several years.   Acting wasn’t a major interest to Ford until his junior year at Ripon College when he first took an acting class...",1942-07-13,"Chicago, Illinois, USA",,148,Harrison Ford,https://image.tmdb.org/t/p/w440_and_h660_face/5M7oN3sznp99hWYQ9sX0xheswWX.jpg,https://themoviedb.org/person/3
...
在人员 ID 上创建节点属性唯一性约束
CREATE CONSTRAINT Person_tmdbId IF NOT EXISTS
FOR (p:Person) REQUIRE p.tmdbId IS UNIQUE
结果
Added 1 constraints

处理大量数据

对于包含大量行(接近数十万或数百万)的文件,LOAD CSV可能会遇到内存问题。对于大型文件,建议通过子句CALL {…​} IN TRANSACTIONS将导入过程拆分为多个较轻的事务。

示例 14. 在多个事务中加载大型 CSV 文件

文件persons.csv包含标题行和总共 869 行。该示例以 200 行的事务加载nameborn列。

persons.csv
person_tmdbId,bio,born,bornIn,died,person_imdbId,name,person_poster,person_url
3,"Legendary Hollywood Icon Harrison Ford was born on July 13, 1942 in Chicago, Illinois.   His family history includes a strong lineage of actors, radio personalities, and models.   Harrison attended public high school in Park Ridge, Illinois where he was a member of the school Radio Station WMTH.  Harrison worked as the lead voice for sports reporting at WMTH for several years.   Acting wasn’t a major interest to Ford until his junior year at Ripon College when he first took an acting class...",1942-07-13,"Chicago, Illinois, USA",,148,Harrison Ford,https://image.tmdb.org/t/p/w440_and_h660_face/5M7oN3sznp99hWYQ9sX0xheswWX.jpg,https://themoviedb.org/person/3
...
以下查询使用变量作用域子句(在 Neo4j 5.23 中引入)将变量导入CALL子查询。如果您使用的是旧版本的 Neo4j,请改用导入WITH子句
查询
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row
CALL (row) {
  MERGE (p:Person {tmdbId: row.person_tmdbId})
  SET p.name = row.name, p.born = row.born
} IN TRANSACTIONS OF 200 ROWS
结果
Added 444 nodes, Set 1332 properties, Added 444 labels
如果发生错误,CALL {…​} IN TRANSACTIONS可能仅导入 CSV 数据的一部分,因为事务已提交。例如,如果前 200 行没有错误,则会提交它们。如果接下来的 200 行包含导致错误的数据,则第二个事务将失败,但不会影响第一个事务。

LOAD CSV 和 Neo4j 函数

使用linenumber()访问行号

linenumber()函数提供LOAD CSV正在操作的行号,或者如果在LOAD CSV上下文之外调用则为null

此函数的一个常见用例是为尚无唯一列的 CSV 数据生成顺序唯一 ID。

示例 15. linenumber()
artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'file:///artists.csv' AS row
RETURN linenumber() AS number, row
结果
number row

1

["1","ABBA","1992"]

2

["2","Roxette","1986"]

3

["3","Europe","1979"]

4

["4","The Cardigans","1992"]

4 行

使用file()访问 CSV 文件路径

file()函数提供LOAD CSV正在操作的文件的绝对路径,或者如果在LOAD CSV上下文之外调用则为null

示例 16. file()
artists.csv
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV FROM 'file:///artists.csv' AS row
RETURN DISTINCT file() AS path
结果
path

'/artists.csv'

即使加载远程 CSV 文件,file()也会始终返回本地路径。对于远程资源,file()会返回其下载到的临时本地路径。

CSV 文件格式

CSV 文件格式和LOAD CSV的交互方式如下

  • 文件字符编码必须为 UTF-8。

  • 行终止符取决于系统(Unix 为\n,Windows 为\r\n)。

  • 默认字段分隔符为,。使用选项FIELDTERMINATOR更改它。

  • CSV 文件可能包含带引号的STRING值,并且在LOAD CSV读取数据时会删除引号。

  • 如果dbms.import.csv.legacy_quote_escaping设置为默认值true,则\用作转义字符。

  • 双引号必须位于带引号的STRING中并进行转义,方法是使用转义字符或第二个双引号。

标题

如果 CSV 文件以包含列名的标题行开头,则文件中的每个导入行都充当映射而不是数组。

您必须通过在查询中添加WITH HEADERS来指示标题行的存在。然后,您可以通过其对应的列名称访问特定字段。

示例 17. 将 CSV 解析为映射列表
artists-with-headers.csv
Id,Name,Year
1,ABBA,1992
2,Roxette,1986
3,Europe,1979
4,The Cardigans,1992
查询
LOAD CSV WITH HEADERS FROM 'file:///artists-with-headers.csv' AS row
MERGE (a:Artist {name: row.Name, year: toInteger(row.Year)})
RETURN
  a.name AS name,
  a.year AS year
结果
name year

"ABBA"

1992

"Roxette"

1986

"Europe"

1979

"The Cardigans"

1992

4 行

添加了 4 个节点,设置了 8 个属性,添加了 4 个标签

字段分隔符

默认字段分隔符为,。使用FIELDTERMINATOR选项指定不同的字段分隔符。

如果您尝试导入一个不使用,作为字段分隔符的文件,并且您也没有指定自定义分隔符,则LOAD CSV会将 CSV 解释为只有一列。

示例 18. 使用;作为字段分隔符导入 CSV
artists-fieldterminator.csv
1;ABBA;1992
2;Roxette;1986
3;Europe;1979
4;The Cardigans;1992
查询
LOAD CSV FROM 'file:///artists-fieldterminator.csv' AS row FIELDTERMINATOR ';'
MERGE (:Artist {name: row[1], year: toInteger(row[2])})
结果
Added 4 nodes, Set 8 properties, Added 4 labels
如果在字段分隔符的 Unicode 字符的十六进制表示形式前加上\u,则可以使用它。使用四位数字编写编码:例如,\u003B等效于;(分号)。

引号转义

CSV 文件中允许使用带引号的STRING值,并且在LOAD CSV读取数据时会删除引号。如果带引号的STRING值必须包含引号字符",则有两种方法可以对其进行转义

  1. 双引号 — 使用另一个引号"来转义引号(例如,STRING The "Symbol"的 CSV 编码为"The ""Symbol""")。

  2. 以反斜杠\为前缀 — 如果配置设置dbms.import.csv.legacy_quote_escaping设置为true(默认值),则\用作引号的转义字符(例如,STRING The "Symbol"的 CSV 编码为"The \"Symbol\"")。

示例 19. 导入使用双引号转义的 CSV
artists-with-escaped-quotes.csv
"1","The ""Symbol""","1992"
"2","The \"Symbol\"","1992"
查询
LOAD CSV FROM 'file:///artists-with-escaped-quotes.csv' AS row
MERGE (a:Artist {id: toInteger(row[0]), name: row[1], year: toInteger(row[2])})
RETURN
  a.id AS id,
  a.name AS name,
  a.year AS year,
  size(a.name) AS size
结果
id name year size

1

'The "Symbol"'

1992

12

2

'The "Symbol"'

1992

12

添加了 2 个节点,设置了 6 个属性,添加了 2 个标签

请注意,nameSTRING,因为它在输出中用引号括起来。第三列输出STRING长度作为size。长度仅计算外引号之间的内容,但不包括引号本身。

检查源数据质量

如果导入失败,则需要检查一些元素以确保源文件未损坏。

  • 标题不一致 — CSV 标题可能与数据不一致。它可能丢失、列数过多或分隔符不同。验证标题是否与文件中的数据匹配。调整格式、分隔符或列。

  • 多余或缺少引号 — 非带引号文本中间的独立双引号或单引号,或带引号文本中未转义的引号可能会导致读取文件时出现问题。转义或删除多余的引号。请参见引号转义

  • 特殊字符或换行符 — 在处理文件中的特殊字符时,请确保它们已加引号或将其删除。

  • 换行符不一致 — 确保整个文件中的换行符一致。

  • 二进制零、BOM 字节顺序标记和其他非文本字符 — 应用程序工具中有时会隐藏不常见的字符或特定于工具的格式,但在纯文本编辑器中会变得明显。如果在文件中遇到此类字符,请将其删除或使用 Cypher 的normalize 函数

在导入之前检查源文件

在将数据导入数据库之前,您可以使用LOAD CSV检查源文件并了解导入数据的形式。

示例 20. 断言正确的行数
// Assert correct line count
LOAD CSV FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS line
RETURN count(*);
结果
count(*)

445

1 行

示例 21. 使用标题采样检查前五行
// Check first 5 line-sample with header-mapping
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS line
RETURN line.person_tmdbId, line.name
LIMIT 5;
结果
line.person_tmdbId line.name

'3'

'Harrison Ford'

'31'

'Tom Hanks'

'32'

'Robin Wright'

'35'

'Sally Field'

'48'

'Sean Bean'

5 行

示例

擦除当前数据库并导入完整的电影数据集
// Clear data
MATCH (n) DETACH DELETE n;

// Create constraints
CREATE CONSTRAINT Person_tmdbId IF NOT EXISTS
FOR (p:Person) REQUIRE p.tmdbId IS UNIQUE;

CREATE CONSTRAINT Movie_movieId IF NOT EXISTS
FOR (m:Movie) REQUIRE m.movieId IS UNIQUE;

// Create person nodes
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row
MERGE (p:Person {tmdbId: toInteger(row.person_tmdbId)})
SET p.name = row.name, p.born = date(row.born);

// Create movie nodes
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row
MERGE (m:Movie {id: toInteger(row.movieId)})
SET
    m.title = row.title,
    m.imdbId = toInteger(row.movie_imdbId),
    m.languages = split(row.languages, '|'),
    m.genres = split(row.genres, '|');

// Create relationships
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/acted_in.csv' AS row
MATCH (p:Person {tmdbId: toInteger(row.person_tmdbId)})
MATCH (m:Movie {id: toInteger(row.movieId)})
MERGE (p)-[r:ACTED_IN]->(m)
SET r.role = row.role;

// Set additional node label
MATCH (p:Person)-[:ACTED_IN]->()
WITH DISTINCT p
SET p:Actor;
结果
Added 1 constraints
Added 1 constraints
Added 444 nodes, Set 1332 properties, Added 444 labels
Added 93 nodes, Set 465 properties, Added 93 labels
Created 372 relationships, Set 372 properties
Added 353 labels
随着数据量的增加,首先创建所有节点,然后通过第二次传递添加关系会更有效。

其他导入数据的方法

有一些其他工具可以将 CSV 数据导入 Neo4j。

  1. neo4j-admin database import命令是导入大型 CSV 文件最有效的方法。

  2. 使用语言库解析 CSV 数据并对 Neo4j 数据库运行创建 Cypher 查询。作为扩展库创建,为开发人员提供通用过程和函数。此库对于复杂的转换和数据操作特别有用。有用的过程包括 apoc.load.jdbc、apoc.load.json 等。

  3. ETL 工具:允许从关系数据库中提取模式并将其转换为图形模型。然后,它负责将数据导入 Neo4j。

  4. Kettle 导入工具映射并执行数据流程步骤,并且非常适合非常大的数据集,尤其是在您已经熟悉使用此工具的情况下。