一、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为可选项,如有多个,用空格隔开,支持以下选项:
  1. –expand -comannds
  2. –verbose
  3. –cache-on-heap[=true/false]
  4. –force[=true/false]默认为false,如设置为true表示在导入数据前将存在的数据库文件删除,可用于需重新导入数据的场景,例如:在导入真实数据前,先导入了测试数据,打算先看看导入后数据是什么样子,那么可以设置–force=true,这样可以对同一个数据库进行重新导入;
  5. –high-io[=true/false]:默认为false,如设置为true
  6. –ignore-empty-strings[=true/false]:确定是否忽略数据空字段,默认为false
  7. –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

(注:此处为了便于阅读使用分行显示,实际操作时不分行,用空格隔开)

执行后:

  1. 创建了名为orders的新数据库(–database=orders);
  2. 创建了LABEL为Customer的节点,节点文件为customers.csv:节点1:ID(编号)为23,name(属性名称)为Delicatessen Inc;节点2:ID(编号)为42,name(属性名称)为Delicious Bakery;这里表头customerId:ID(Customer)的Customer定义了该节点的group为Customer,目的是防止在跨实体查询节点编号时有重复的ID编号。
  3. 创建了LABEL为Product和Food的节点(LABEL定义来自products.csv的表头),节点文件为products.csv,节点1:ID(编号)为11,name(属性:名称)为Chocolate,price(属性:价格)为10。
  4. 创建了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的数据列,这两个文件被重复使用)
  5. 创建了关系类型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。
  6. 创建了关系类型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,无其他关系属性。
  7. 设置trim-strings=true表示:如字符串值为空白行,则认为该值为null。

五、导入后在neo4j browser/desktop查询数据

  1. 使用neo4j-admin import前关闭server;
  2. 执行neo4j-admin import命令,database=dbName,确认导入成功;
  3. 打开neo4j browser/desktop server;
  4. 创建与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