Neo4j权威指南 (图数据库技术丛书)
上QQ阅读APP看书,第一时间看更新

2.5 批量导入工具的使用

在初次使用Neo4j图数据库时,很多读者需要将自己使用的关系数据库或用其他存储形式存储的数据批量导入到Neo4j图数据库中。为此,本节将介绍怎样使用Neo4j导入工具来批量导入数据。

目前,导入到Neo4j的工具有两种:load csv指令和neo4j-import工具,这两种都是基于CSV文件的,既然需要CSV文件,那么有必要先考虑如何从其他数据库中获取CSV文件。

先介绍从传统的关系数据库导出CSV文件,然后用Neo4j的两种导入工具导入到Neo4j数据库中,本节只介绍导入工具的实际操作步骤,关于两种导入工具的更详细参数及使用方法参见“5.6 Neo4j数据库管理相关工具”一节。

2.5.1 获取CSV文件

下面介绍几种主流关系数据库导出CSV文件的方法。

2.5.1.1 SQL Server导出CSV文件

打开一个查询窗口,输入SQL语句查询出需要导出的数据列表,如图2-63所示。

图2-63 SQL查询

在查询的结果栏目中,复制所有查询出来的数据。右击,在快捷菜单中选择“将结果另存为”,如图2-64所示。

图2-64 查询结果另存为

这里可以选择保存为CSV文件或者是txt文件,我们选择CSV文件,如图2-65所示。用Excel打开CSV文件,就可以看到CSV文件的内容了。

图2-65 保存CSV文件

2.5.1.2 MySQL导出CSV文件

MySQL支持将查询结果直接导出为CSV文本格式,在使用select语句查询数据时,在语句后面加上导出指令即可,格式如下:

● into outfile <导出的目录和文件名>:指定导出的目录和文件名。

● fields terminated by <字段间分隔符>:定义字段间的分隔符。

● optionally enclosed by <字段包围符>:定义包围字段的字符(数值型字段无效)。

● lines terminated by <行间分隔符>:定义每行的分隔符。

下面举一个使用MySQL导出CSV文件的例子:

【程序2-18】MySQL导出CSV文件

    select * from mydatatable where mytag like 'E1%'
    into outfile 'E:\E1.csv' fields terminated by ', ' optionally enclosed by '"'
    lines terminated by '\r\n';

此条指令执行后,会把mydatatable表中部分匹配查询条件的记录导出到E1.csv文件中。其中每个字段以逗号分隔,字段内容是以双引号包围的字符串,每条记录使用\r\n换行,如图2-66所示。

图2-66 CSV文件格式

2.5.1.3 Oracle导出CSV文件

可以使用sqlplus导出CSV文件,这是比较方便的一种方式,当然读者也可以考虑采用其他方式。

首先创建spool.sql文件,内容如下:

【程序2-19】创建spool.sql文件

    set colsep ,
    set feedback off
    set heading off
    set trimout on
    spool E:\user.csv
    select '"' || user_name || '", "' || user_age || '", "' || user_card || '", "'
    || user_sex || '", "' || user_addres || '", "' || user_tel || '"'  from user_
    bl;
    spool off
    exit

然后,运行sqlplus命令:

    sqlplus -s用户名/密码@数据库名 @spool.sql

这样就从Oracle中将lfc_ bl表中的数据导出到E:\lfc_ bl.csv里面了。

对于spool.sql文件的指令详细解析请参考表2-2所示。

表2-2 sqlplus命令参照

2.5.1.4 CSV内容格式注意事项

Neo4j对CSV文件的格式是有要求的,在讨论如何导入CSV之前,先把CSV文件中一些常见的错误列举出来。读者可以使用文本编辑器打开自己的CSV文件查看是否出现以下错误。

CSV文件内容格式常见错误如下:

(1)在CSV文件开始处存在BOM字节顺序标记(2个UTF-8字符),如果存在需要删除它们。

(2)文件内存在非文本类型的字符,如果存在就删除它们。

(3)存在不规则换行符,如:混合Windows和UNIX换行符,如果有需要确保它们一致,最好选择UNIX风格。

(4)CSV文件头与数据不一致(内容相比头缺少列或多出列,头中有不同的分隔符),如有此情况需要修复头部。

(5)带引号和不带引号的文本字段中出现换行符,如存在就删除换行符。

(6)存在杂散的引号,非文本中存在独立双引号或单引号,如存在就转义或删除杂散引号。

2.5.2 使用Load CSV指令导入到Neo4j

Neo4j提供了Load CSV命令帮助我们将CSV数据文件导入到Neo4j中,下面给出几个读取CSV文件,但不存入数据库的例子。

2.5.2.1 简单导入CSV数据

Load CSV读取但不存入数据库:

    // 查看前CSV文件行数
    LOAD CSV FROM "file-url" AS line
    RETURN count(*);
    // 查看前CSV文件前5行
    LOAD CSV FROM "file-url" AS line WITH line
    RETURN line
    LIMIT 5;
    //查看前CSV文件,并带有头部数据
    LOAD CSV WITH HEADERS FROM "file-url" AS line WITH line
    RETURN line
    LIMIT 5;

上述例子仅仅是用来读取CSV文件,它并没有将数据存入到数据库中。下面介绍Load CSV的用法。

LOAD CSV FROM "file-url" AS line,这条指令就是将指定路径下的CSV文件读取出来,其中"file-url"就是文件的地址,可以是本地文件路径也可以是网址,只要能从地址中读取到CSV文件即可,因此也可以这样写:

    LOAD CSV FROM 'http://we-yun.com/neo4jguide/movie.csv' AS line
    RETURN line

这样就可以读取网址指定的movie.csv文件。

或者可以使用本地文件路径:

    LOAD CSV FROM ' file:///E:/products.csv' AS line
    RETURN line

这样就可以读取到E:/products.csv文件。

如果把CSV文件放置在Neo4j系统路径的import文件夹内,就只不需要指定CSV文件的路径,如下所示,可以读取到放入import文件夹内的products.csv文件。

    LOAD CSV FROM ' file:/// products.csv' AS line
    RETURN line

对于Return语句,它是用来返回并显示结果到结果显示区的语句。

对于Limit语句,是用来限制返回的行数。

这样就可以读取CSV文件了,但它并没有存入到数据库中,要导入到Neo4j数据库中需要使用相应的Create语句,下例可以读取网址指定的movie.csv文件并批量创建节点Movie,每个节点的title、released和tagline属性由导入的CSV文件的每行指定。

    LOAD CSV FROM 'http://we-yun.com/neo4jguide/movie.csv' AS line
    CREATE (:Movie { title: line[0] , released: line[1] , tagline: line[2]})

执行完上面语句后,会看到结果显示区显示了所创建的节点数量,如图2-67所示。

图2-67 显示区显示了所创建的节点数量

然后,用以下语句来查看下数据库内是否已经有导入的数据了:

    MATCH (n:Movie) RETURN n

运行上面语句后,可以得到如图2-68所示的结果。

图2-68 查询导入后结果

如上图所示,这说明已经导入数据成功了。

2.5.2.2 导入CSV时附带表头

下例介绍如何在导入CSV时附带上表头。

    LOAD CSV WITH HEADERS FROM 'http://we-yun.com/neo4jguide/tracks.csv ' AS line
    CREATE (:Track { TrackId: line.Id, Name: line.Track, Length: line.Length})

上述语句添加了WITH HEADERS子句,它的功能就是在导入CSV时附带上头部,头部由line.Id、line.Track指定。执行完上面语句后,可使用下面语句查看一下:

    MATCH (n:Track) RETURN n

将得到如图2-69所示的结果。

图2-69 查询导入后结果

可以看到,每个数据元素都带有TrackId、 Name、Length头部元素。

2.5.2.3 导入CSV大文件

如果要导入包含大量数据的CSV文件,则可以使用PERODIC COMMIT子句。

使用PERIODIC COMMIT指示Neo4j在执行完一定行数后提交数据再继续,这样减少了内存开销。

使用PERIODIC COMMIT默认值为1000行,因此数据将每一千行提交一次。

要使用PERIODIC COMMIT,只需在LOAD CSV语句之前插入USING PERIODIC COMMIT语句。

具体使用方法如下所示。

      USING PERIODIC COMMIT
      LOAD CSV WITH HEADERS FROM 'http://we-yun.com/neo4jguide/tracks.csv' AS line
      CREATE (:Track { TrackId: line.Id, Name: line.Track, Length: line.Length})

可以让其每800行提交一次,如下所示。

    USING PERIODIC COMMIT 800
    LOAD CSV WITH HEADERS FROM 'http://we-yun.com/neo4jguide/tracks.csv' AS line
    CREATE (:Track { TrackId: line.Id, Name: line.Track, Length: line.Length})

2.5.3 使用neo4j-import工具导入到Neo4j

从Neo4j 2.2版本开始,系统就自带了一个大数据量的导入工具:neo4j-import,可支持并行、可扩展的大规模CSV数据导入。下面介绍使用这个工具导入CSV数据。

首先,可以在Neo4j系统目录下的path/to/neo4j/bin/neo4j-import路径下找到这个工具的可执行文件。下面是使用示例:

    bin/neo4j-import --into retail.db --id-type string \
                  --nodes:Customer customers.csv --nodes products.csv  \
                  --nodes:orders_header.csv, orders1.csv, orders2.csv \
                  --relationships:CONTAINS order_details.csv \
                  --relationships:ORDERED
    customer_orders_header.csv, orders1.csv, orders2.csv

上例中以“--nodes:”子句开头的CSV文件是节点csv文件;以“--relationships:”开头的是关系CSV文件;“--into”子句指明了导入的Neo4j数据库名称;“--id-type”子句指明了生成节点、关系的主键类型为string类型。

由于neo4j-import工具不能使用Cypher语句创建节点、关系,所以需要为节点和关系分别提供不同的csv文件。上例中各个文件的列的组织形式如表2-3~表2-7所示。

表2-3 customers.csv文件格式

表2-4 products.csv文件格式

表2-5 orders_header.csv, orders1.csv, orders2.csv文件格式

表2-6 order_details.csv文件格式

表2-7 customer_orders_header.csv, orders1.csv, orders2.csv文件格式

对于上面各个CSV文件的内容解析如下:

(1)customers.csv中的全部记录将作为节点直接导入到Neo4j数据库中,其中节点都带有Customer标签节点属性,直接从CSV文件的每条记录中获取。

(2)products.csv文件导入形式与customers.csv相同,但其中节点标签取自:LABEL列(Product或者Food)。

(3)对于节点的顺序取自3个文件(orders_header.csv、orders1.csv、orders2.csv),一个头文件和两个内容文件。

(4)接下来需要创建订单项(orders1.csv、orders2.csv)与所包含的产品(products.csv)相关联关系“CONTAINS”,这个关联关系是从order_details.csv创建的,通过其ID将订单与所包含的产品相关联。

(5)订单可以通过orders1.csv、orders2.csv文件关联到客户。

初学者可以参照本例中各个CSV文件的列格式制作自己的CSV文件,再使用neo4j-import工具进行导入。