一、neo4j-admin简要介绍
neo4j-admin是管理neo4j DBMS的主要工具之一,是一种命令行工具。
neo4j admin命令需与当前neo4j用户一致。
(1)位置:以neo4j desktop为例,neo4j-admin在当前project下活动的database的dbms文件夹下的bin文件夹中。
(2)启动方式:
- 打开当前project的terminal;
- 进入bin文件夹:执行cd bin,此时,输入neo4j-admin XX(命令)即可。
(3)语法:neo4j-admin [-hv] [COMMAND],常用命令如下:
注意环境和neo4j-admin 版本!
- neo4j-admin -h 或neo4j-admin –help:显示neo4j-admin帮助信息;
- neo4j-admin -v 或neo4j-admin –version:打印neo4j-admin版本信息;
- neo4j-admin import:从一系列CSV文件中导入数据,使用详见下一节。
二、neo4j-admin import命令
(1)用途:可用于批量导入CSV数据。
(2)前提:使用者必须有权限对dbmis.directories.data 和dbms.directories.log进行写入操作。
(3)特点:仅可用于初始化未运行的空数据库或创建新的数据库,即:即便一个已存在的存储过数据的数据库被清空也无法执行import命令。
(4)vs LOAD CSV:
LOAD CSV | 用于将中小型CSV文件数据导入已存在的数据库 可按需执行LOAD CSV命令多次 |
neo4j-admin import | 用于批量导入格式化的CSV文件 仅可对空数据库使用一次 注意:该命令为离线运行,即:执行该命令前数据库应处于未运行状态(关闭server),执行后许重启neo4j sever,详见下文。 |
(5)import 命令的使用:
neo4j-admin import [Options]
- Options为可选项,如有多个,用空格隔开,支持以下选项:
- –expand -comannds:
- –verbose:
- –cache-on-heap[=true/false]:
- –force[=true/false]:默认为false,如设置为true表示在导入数据前将存在的数据库文件删除,可用于需重新导入数据的场景,例如:在导入真实数据前,先导入了测试数据,打算先看看导入后数据是什么样子,那么可以设置–force=true,这样可以对同一个数据库进行重新导入;
- –high-io[=true/false]:默认为false,如设置为true
- –ignore-empty-strings[=true/false]:确定是否忽略数据空字段,默认为false
- –trim-strings=[true/false]:确定是否在遇到空白行时认为是null,默认为false
三、CSV格式化文件
neo4j-admin import命令处理的CSV文件需要满足特定的格式,即CSV格式化文件,分为两类:节点文件(node files) 和 关系文件(relationship files)。基本格式为键值对,如下:
:
- name:指节点属性和节点ID,其他字段如LABEL等省略name;
- field_type:指字段类型,例如:ID、LABEL等。
(1)其他要求
- CSV文件的编码格式需为UTF-8。
(2) 建议
- 表头单独建文件,以便处理和编辑;
- 用文本编辑器如notepad、vscode等编辑CSV文件,不建议直接用excel或wps编辑,容易导致乱码等问题。
3.1节点文件格式
CSV节点文件的表头格式如下:
, , , …,
- nodeId:ID:自定义的节点编号,对于每个节点这个编号是唯一的,用于创建关系等后续import操作时索引到指定节点;
- propertyNameX:节点属性,对于属性,field_type指data_type,默认为string,可定义的data_type如下表所示;
- :LABEL:(注意前面有冒号,省略了name)非必选,用于指定节点的标签,1个节点可以有多个标签,赋值时多个标签之间用该CSV文件的分隔符隔开,默认为“;”。
属性可定义的data_type(field_type): | |
---|---|
数值类 | int, long, float, double |
布尔值 | boolean |
字符类 | byte, short, char, string |
点类型 | point |
日期时间 | date, localtime, time, localdatetime, datetime, duration |
例1:movies.csv,文件内容如下:
movieId:ID,title,year:int,:LABELtt0133093,"The Matrix",1999,Moviett0234215,"The Matrix Reloaded",2003,Movie;Sequeltt0242653,"The Matrix Revolutions",2003,Movie;Sequel
movies.csv 定义了3个(电影)节点:
- 节点1:ID为tt0133093,名字为The Matrix,年份为1999(整数类型),标签为Movie;
- 节点2:ID为tt0234215,名称为The Matrix Reloaded,年份为2003(整数类型),标签为Movie和Sequel;
- 节点3:ID为tt0242653,名字为The Matrix Revolutions,年份为2003(整数类型),标签为Movie和Sequel。
例2:actors_header.csv及actors.csv,文件内容如下:
actors_header.csv:personId:ID,name,:LABEL
actors.csv:keanu,"Keanu Reeves",Actorlaurence,"Laurence Fishburne",Actorcarrieanne,"Carrie-Anne Moss",Actor
actors_header.csv和actors.csv定义了3个(演员)节点:
- 节点1:ID为keanu,名字为Keanu Reeves,标签为Actor;
- 节点2:ID为laurence,名字为Laurence Fishburne,标签为Actor;
- 节点3:ID为carrieanne,名字为Carrie-Anne Moss,标签为Actor。
3.2关系文件格式
CSV关系文件基本的表头格式为:
, , , ,…
- :START_ID:关系的起始节点编号(The ID of the start node for this relationship)必须有;
- :TYPE:关系的类别(relationship types),例如:WORKS_FOR, CONTAINS…,必须有;
- :END_ID:关系的结束节点编号(The ID of the end node for this relationship),必须有;
- RelationshipPropertiesNameX:关系的属性,非必须。
- 和不需要定义name,如果定义了:或:,则自动忽略。
例3:(基于例1、例2)roles_header.csv和roles.csv内容如下:
roles_header.csv::START_ID,role,:END_ID,:TYPE
roles.csv:keanu,"Neo",tt0133093,ACTED_INkeanu,"Neo",tt0234215,ACTED_INkeanu,"Neo",tt0242653,ACTED_INlaurence,"Morpheus",tt0133093,ACTED_INlaurence,"Morpheus",tt0234215,ACTED_INlaurence,"Morpheus",tt0242653,ACTED_INcarrieanne,"Trinity",tt0133093,ACTED_INcarrieanne,"Trinity",tt0234215,ACTED_INcarrieanne,"Trinity",tt0242653,ACTED_IN
roles_header.csv和roles.csv定义了一类关系,创建了9条关系:
- 关系1:ID为keanu的Actor ACTED_IN ID为tt0133093的Movie,扮演的role为Neo;
- 关系2:ID为keanu的Actor ACTED_IN ID为tt0234215的Movie,扮演的role为Neo;
- 关系3:ID为keanu的Actor ACTED_IN ID为tt0242653的Movie,扮演的role为Neo;
- 关系4:ID为laurence的Actor ACTED_IN ID为tt0133093的Movie,扮演的role为Morpheus;
- 关系5:ID为laurence的Actor ACTED_IN ID为tt0234215的Movie,扮演的role为Morpheus;
- 关系6:ID为laurence的Actor ACTED_IN ID为tt0242653的Movie,扮演的role为Morpheus;
- 关系7:ID为carrieanne的Actor ACTED_IN ID为tt0133093的Movie,扮演的role为Trinity;
- 关系8:ID为carrieanne的Actor ACTED_IN ID为tt0234215的Movie,扮演的role为Trinity;
- 关系9:ID为carrieanne的Actor ACTED_IN ID为tt0242653的Movie,扮演的role为Trinity。
3.3 补充说明
(1)除name:ID、:LABEL、:START_ID、:END_ID、:TYPE外的列都被认为是属性:
- 如果“:”前名称省略,则该列数据读取;
- 如果为“name:”或者为“:IGNORE”,则该列数据不读取。
(2)name:ID:该键值对的设置是为了设置全局ID用于后续查询节点时使用:
- 如果跨实体有重复的ID编号,则需要按照“name:ID(group)”形式设置该键值对;
- 如果定义的ID编号是全局唯一的,不需要定义group。
3.4 常见坑
(1)表头问题:表头与数据不一致,例如:缺失列、多列、表头分隔符与数据分隔符不一致等。在导入CSV文件时,提前确认表头没有这些问题将节省大量时间。
(2)引号问题:文件正文内容中引号,需要考虑转义问题。
3.5 常用数据清洗工具
(1)CSVKit:python提供一系列数据清洗和格式化工具,如csvstat、csvgrep等。
(2)CSVLint:一种线上处理CSV文件的网站,CSV Lint | Check your CSV files with CSVLint
(3) papa parse:Javascript库用于处理CSV文件。
四、使用neo4j-admin import命令批量处理CSV文件
举例说明批量处理方法:
import文件夹下现有以下CSV文件:
(1)cutomers.csv
customers.csv:customerId:ID(Customer), name23, Delicatessen Inc42, Delicious Bakery
(2)products.csv
products.csv:productId:ID(Product), name, price, :LABEL11,Chocolate,10,Product;Food
(3)orders_header.csv
orders_header.csv:orderId:ID(Order),date,total,customerId:IGNORE
(4)customer_orders_header.csv
customer_orders_header.csv::END_ID(Order),date:IGNORE,total:IGNORE,:START_ID(Customer)
(5)orders1.csv
orders1.csv:1041,2020-05-10,130,23
(6)orders2.csv
orders2.csv:1042,2020-05-12,20,42
(7)order_details.csv
order_details.csv::START_ID(Order),amount,price,:END_ID(Product)1041,13,130,111042,2,20,11
执行如下neo4j-admin命令:
../bin/neo4j-admin import --database=orders --nodes=Customer=import/customers.csv --nodes=import/products.csv --nodes=Order="import/orders_header.csv,import/orders1.csv,import/orders2.csv" --relationships=CONTAINS=import/order_details.csv --relationships=ORDERED="import/customer_orders_header.csv,import/orders1.csv,orders2.csv" --trim-strings=true
(注:此处为了便于阅读使用分行显示,实际操作时不分行,用空格隔开)
执行后:
- 创建了名为orders的新数据库(–database=orders);
- 创建了LABEL为Customer的节点,节点文件为customers.csv:节点1:ID(编号)为23,name(属性名称)为Delicatessen Inc;节点2:ID(编号)为42,name(属性名称)为Delicious Bakery;这里表头customerId:ID(Customer)的Customer定义了该节点的group为Customer,目的是防止在跨实体查询节点编号时有重复的ID编号。
- 创建了LABEL为Product和Food的节点(LABEL定义来自products.csv的表头),节点文件为products.csv,节点1:ID(编号)为11,name(属性:名称)为Chocolate,price(属性:价格)为10。
- 创建了LABEL为Order的节点,节点文件为orders_header.csv、orders1.csv、orders2.csv,节点1:ID(编号)为1041,date(属性:日期)为2020-05-10,total(属性:总数)为130;节点2:ID(编号)为1042,date(属性:日期)为2020-05-12,total(属性:总数)为20。:IGNORE列表示省略(该列设置的目的是为了对应orders1.csv和orders2.csv的数据列,这两个文件被重复使用)
- 创建了关系类型Type为CONTAINS的关系,关系文件为orders_details.csv,关系1:START_ID(起始节点编号)为group为Order的1041,END_ID(结束节点编号)为group为Product的11,amount(属性:数量)为13,price(属性:价格)为130;关系2:START_ID(起始节点编号)为group为Order的1042,END_ID(结束节点编号)为group为Product的11,amount(属性:数量)为2,price(属性:价格)为20。
- 创建了关系类型Type为ORDERED的关系,关系文件为customer_orders_header.csv、orders1.csv、orders2.csv,关系1:START_ID(起始节点编号)为group为Customer的23,END_ID(结束节点编号)为group为Order的1041,关系无属性;关系2:START_ID(起始节点编号)为group为Customer的42,END_ID(结束节点编号)为group为Order的1042,无其他关系属性。
- 设置trim-strings=true表示:如字符串值为空白行,则认为该值为null。
五、导入后在neo4j browser/desktop查询数据
- 使用neo4j-admin import前关闭server;
- 执行neo4j-admin import命令,database=dbName,确认导入成功;
- 打开neo4j browser/desktop server;
- 创建与database名称相同的数据库(即执行:create databasedbName),切换到该数据库(dbName)后即可使用查询语句。
参考:Re: Neo4j-admin import successful but no data show… – Neo4j – 13384neo4j import显示成功但是查询没有数据_mydoubts的博客-CSDN博客_neo4j导入csv文件成功但查不到数据
本文参考neo4j官方文档:
Import – Operations Manual
Importing CSV Data into Neo4j – Developer Guides