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 使用凭据从远程文件导入艺术家姓名和年份信息
ftp://<username>:<password>@<domain>/bands/artists.csv
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 文件

CSV 列可以动态引用,将标签映射到图中的节点。这使得数据处理更加灵活,允许标签从 CSV 列值中填充,而无需手动指定每个条目。它还降低了 Cypher® 注入的风险。(有关 Cypher 注入的更多信息,请参阅Neo4j 知识库 → 防范 Cypher 注入)。

bands-with-headers.csv
Id,Label,Name
1,Band,The Beatles
2,Band,The Rolling Stones
3,Band,Pink Floyd
4,Band,Led Zeppelin
查询
LOAD CSV WITH HEADERS FROM 'file:///bands-with-headers.csv' AS line
MERGE (n:$(line.Label) {name: line.Name})
RETURN n AS bandNodes
结果
bandNodes

(:Band {name: 'The Beatles'})

(:Band {name: 'The Rolling Stones'})

(:Band {name: 'Pink Floyd'})

(:Band {name: 'Led Zeppelin'})

行数: 4
添加了 4 个节点,设置了 4 个属性,添加了 4 个标签

使用动态值的 MERGE 查询可能不如使用静态值的查询性能好。这是因为 Cypher 规划器在规划查询时使用静态可用信息来确定是否使用索引,这在使用动态值时是不可能的。有关更多信息,请参阅MERGE 使用动态节点标签和关系类型 → 性能注意事项

导入压缩的 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 关系隐式地将演员定义为人物的一个子集。以下查询会为所有具有传出 :ACTED_IN 关系的 Person 添加一个额外的 Actor 标签。

查询
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,contact@neo4j.com,P
2,AAA,,info@aaa.com,
3,BBB,Chicago, ,G
,CCC,Michigan,info@ccc.com,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() 访问行号

LOAD CSV 操作时,linenumber() 函数提供行号,如果在 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 文件路径

LOAD CSV 操作时,file() 函数提供文件的绝对路径,如果在 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'

file() 始终返回本地路径,即使在加载远程 CSV 文件时也是如此。对于远程资源,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

name

1992

"ABBA"

1986

"Roxette"

1979

"Europe"

1992

4 行

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

"The Cardigans"

字段分隔符

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

如果您尝试导入一个不使用 , 作为字段分隔符的文件,并且您也没有指定自定义分隔符,LOAD CSV 会将该 CSV 文件解释为只有一列。
示例 18. 使用 ; 作为字段分隔符导入 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
artists-fieldterminator.csv

如果您在 Unicode 字符的十六进制表示前加上 \u,则可以使用它作为字段分隔符。使用四位数字编写编码:例如,\u003B 等同于 ;(分号)。

引号转义

  1. CSV 文件中允许带引号的 STRING 字符串值,当 LOAD CSV 读取数据时,引号会被去除。如果带引号的 STRING 值必须包含引号字符 ",有两种转义方法:

  2. 双引号 — 使用另一个引号 " 来转义引号(例如,STRING 字符串 The "Symbol" 的 CSV 编码是 "The ""Symbol""")。

前缀反斜杠 \ — 如果配置设置 dbms.import.csv.legacy_quote_escaping 设置为 true(默认值),则 \ 用作引号的转义字符(例如,STRING 字符串 The "Symbol" 的 CSV 编码是 "The \"Symbol\"")。
示例 19. 导入带双引号转义的 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
结果
artists-with-escaped-quotes.csv name year id

1

size

1992

12

2

size

1992

12

'The "Symbol"'

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

请注意,name 是一个 STRING 字符串,因为它在输出中被引号包围。第三列将 STRING 字符串长度输出为 size。长度只计算外部引号之间的内容,不包括引号本身。

检查源数据质量

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

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

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

  • 特殊字符或换行符 — 处理文件中的特殊字符时,请确保它们被引用或将其移除。

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

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

导入前检查源文件

在将数据导入数据库之前,您可以使用 LOAD CSV 检查源文件,了解导入数据将具有的形式。
// Assert correct line count
LOAD CSV FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS line
RETURN count(*);
结果
示例 20. 断言正确的行数

445

count(*)

1 行
// 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;
结果
示例 21. 检查前五行(带标题采样) line.person_tmdbId

'3'

'Harrison Ford'

'31'

'Tom Hanks'

'32'

'Robin Wright'

'35'

'Sally Field'

'48'

'Sean Bean'

5 行

line.name

示例
// 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
擦除当前数据库并导入完整的电影数据集

随着数据量的增加,更有效的方法是先创建所有节点,然后通过第二次处理添加关系。

其他导入数据的方式

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

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

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

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

© . All rights reserved.