安装 neo4j 数据库

1. 下载

进入 neo4j 官方网站的下载页面,根据所用操作系统,下载适当的版本。

因为企业版需要授权,因此可暂先下载社区版本,下面以 Linux 系统为例:

# 下载
$ wget https://neo4j.com/artifact.php?name=neo4j-community-3.4.1-unix.tar.gz

# 解压
$ tar zxvf ./neo4j-community-3.4.1-unix.tar.gz

2. 配置

下载并解压后得到的目录形如:

$ tree ./neo4j-community-3.4.1-unix
.
├── bin/ # <- 可执行程序
├── certificates/
├── conf/ # <- 配置文件
├── data/ # <- 数据库中的数据
├── import/
├── lib/
├── logs/
├── plugins/
├── run/
├── LICENSES.txt
├── LICENSE.txt
├── NOTICE.txt
├── README.txt
└── UPGRADE.txt

2.1 配置环境变量

配置环境变量 NEO4J_HOME 值为该目录的地址。还可将 bin 目录加入 PATH

2.2 设置数据库服务的地址与端口

打开 conf/neo4j.conf 文件,找到下面内容:

# Bolt connector
dbms.connector.bolt.enabled=true
#dbms.connector.bolt.tls_level=OPTIONAL
#dbms.connector.bolt.listen_address=:7687  <# neo4j 操作指南

# HTTPS Connector. There can be zero or one HTTPS connectors.
dbms.connector.https.enabled=true
#dbms.connector.https.listen_address=:7473 <--- 

打开上面箭头所指行的注释,并在冒号前加上本机的 ip 地址,如改为:

dbms.connector.https.listen_address=0.0.0.0:7687

3. 运行

运行 bin 目录下的 neo4j 命令。

$ sudo neo4j start

此时数据库系统已经启动了,如果遇到问题,可以查看 logs/ 中的日志文件,定位错误。

neo4j 数据库数据导入指南

在初始化数据库的时候,通常需要导入大量的数据,此时需要采用一种批量导入的方法,而非一条条插入。下面内容描述了如何准备数据,以及如何将数据导入 neo4j 数据库中。

本文主要参考了 neo4j 的关于导入数据的文档 Use the Import tool ,并结合自己的实践经验做了些许说明。

neo4j 图数据库核心概念介绍

在关系型数据库中,如 MySql,数据以元组形式存储,多个同型元组构成表,表与表之间通过外键进行关联。在 neo4j 图数据库中,数据以节点(Node)存储,每个节点可以有各自的属性,节点间通过关系相连。

上图中,存在 3 个节点,其中 2 个 Person 节点,1 个 Movie 节点。节点各自包含自身的,Person 和 Movie 间通过 AVTED_INDIRECTED 连接。关系自身也可包含属性,比如 ACTED_IN 中包含了 roles 属性,指明 Person 在 Movie 中饰演什么角色。

数据导入主要思想

在图数据库中,核心有两个,即节点和关系。通常一个图数据库中会含多类节点,和连接这各类节点的关系。neo4j 提供了向数据库中导入海量数据的工具 neo4j-admin import,使用该工具导入数据,比使用插入语句要快很多。

该工具要求待导入数据以 csv 格式存储,节点与关系的数据需要按照约定的格式存储在 csv 文件中,neo4j 的导入工具读取并导入这些数据。

具体操作方法可以参考 Use the Import tool,或者阅读下面的简化版操作指南。

数据导入方法

1. 数据准备

构建数据库,第一步要确定存在哪些类型的节点,以及节点间有哪些关系。下面假想一个场景。

在人才招聘网站的图数据库中,可能包含 求职者公司职位简历 这四类节点。

四类节点通过以下关系相连:

  • 求职者 –浏览–> 职位
  • 求职者 –申请–> 职位
  • 求职者 –创建–> 简历
  • 公司 –发布–> 职位

要构建数据库,需要提供这些节点和关系对应的数据。

1.1 数据格式说明

neo4j 的导入工具要求数据以 csv 格式存储,且规定了一些特殊的格式。

csv 文件头部格式

一个 csv 文件中,通常存放的是同类数据,其中的每一行为一个元素,每一列为一个属性。文件的第一行为头部,记录了各列的属性名。

neo4j 导入工具对 csv 头部做了部分扩展。在其格式形如:

<field_name>:<field_type>, <field_name>:<field_type>, <field_name>:<field_type>

其中 <field_name> 为属性名,冒号后面的 <field_type> 指明该属性的类型。类型可忽略,默认会使用 string 类型。

因为 csv 中数据均以文本形式存储,<field_type> 是为了明确指明各个字段的数据类型。可选的类型如下:

int, long, float, double, boolean, byte, short, char,
string, point, date, localtime, time,localdatetime,
datetime, duration

举例如下:

用户编号:string, 简历编号, 简历编号, 简历名称, 性别, 年龄:int
6717, 18294R9, 4658, 销售主管, 男, 28

节点数据

每一类节点都有不同的属性,因此通常不同类型的节点会存放在不同的 csv 文件中。采用前面提到的格式,把节点数据整理为 csv 文件。而后,对于节点数据,需要对 csv 的头部再做适当扩展。

每一个节点,需要有一个 id 来标识。在 csv 文件头部需要有一个特殊的 ID 类型的字段,该字段的值在当前文件中要唯一。

另外,每个节点都有其标签。通过增加一个类型为 LABEL 的列来指明节点标签。

举例如下 applicants.csv :

用户编号:ID, age:int,gender:string,:LABEL
1698,27,'女',求职者
1699,23,'女',求职者

applicants.csv 文件中,用户编号:ID 指明以用户编号作为节点的 id。最后一列,:LABEL,指明了节点的标签。

关系数据

一个关系最基本的要素为:关系名、关系起点、关系终点。在记录关系数据的 csv 文件的头部,至少要指出这三种信息。

browse.csv 为例:

用户编号:START_ID,职位编号:END_ID,:TYPE
1699,3122,浏览

START_ID 指出关系的起始结点的 id,END_ID 指出关系的终点的 id,而 TYPE 指出关系类型。这里的 START_IDEND_ID 的值均对应一个节点的 ID。

上面这一条数据,就给 id 为 1699 的用户和编号为 3122 的职位间建立了 浏览 的关系。

补充说明

如果不同的节点有相同的 id,比如节点 id 按行递增时,这个时候在关系数据中 START_IDEND_ID 所指就不唯一了。解决方法是给 ID 增加命名空间。

用户编号:ID(USER_ID), age:int,gender:string,:LABEL
1698,27,'女',求职者

职位编号:ID(JOB_ID), 职位名称,:LABEL
3122,C++工程师,职位

用户编号:START_ID(USER_ID),职位编号:END_ID(JOB_ID),:TYPE
1699,3122,浏览

这里使用类似 ID(USER_ID) 的写法,为不同节点的 ID 定义了命名空间,这样以来不同节点间相同的 ID 也就不会冲突了。

2. 导入数据

neo4j 提供了命令行工具来完成大量数据导入,其可执行文件为 <neo4j_home>/bin/neo4j-admin。其中 <neo4j_home> 为 neo4j 的安装目录。

可以通过下面的命令导入数据:

$ neo4j-admin import \ 
    --nodes=applicants.csv --nodes=job.csv \ # 指定节点文件
    --relationships=browse.csv --relationships=deliver.csv \  # 指定关系文件
    --delimiter=";" \ # 指定 csv 的分隔符,默认为英文逗号 (,)
    --array-delimiter="|" \ # csv 文件中某个字段为数组时,数组元素间的分隔符

即通过 --nodes--relationships 选项,将结点和关系对应的 csv 文件传给导入工具。

neo4j-admin import 命令有很多的参数,具体可以参见 文档 1文档 2

使用导入工具

如果需要要导入的文件很多,命令行就会很长。这里提供了一段 python 脚本,通过编写配置文件,生成相应的命令并执行,以缓解输入很长命令的麻烦。

import.py 可以在此处获得。

用法如下:

$ python import.py config.json

其中 config.json 为配置文件,文件格式如下:

{   
    "neo4j_home": "/home/xx/neo4j-community",
    "database": "graph.db", // 指定数据库名,默认为 `graph.db`
    "nodes": [{ // 指定节点对应的 csv 文件
        "header": "./data/user_header.csv",
        "file": "./data/user.csv",
        "labels": ["USER"]
    },{ 
        "file": "./data/job.csv",
    }],
    "relationships": [{ // 指定关系对应的 csv 文件
        "file": "./data/browse.csv",
        "types": ['BROWSE']
    }],
    "delimiter": ",",
    "array-delimiter": ";",
    "quote": "\"",
    "ignore-duplicate-nodes": true,
    "ignore-missing-nodes": true
}

各字段说明如下:

=> neo4j_home

此字段用于指定 neo4j 的主目录,便于定位可执行文件 neo4j-admin 的位置。

=> nodes / relationships

提供节点和关系的数据。

  • labels/types

在节点和关系对应的 csv 文件中,可以不添加 :LABEL 或者 :TYPE 列,而在配置文件中使用 labestypes 指出。因为一个节点可以有多种 label,相似地一个关系也可以有多个 type,因此这里使用数组。

  • header:

CSV 文件含两个部分,header 和 body,可以将 header 部分单独放在一个文件中。

=> delimiter

指定 csv 的列分隔符,默认为英文逗号 (,)。

=> array-delimiter

csv 文件中某个字段为数组时,数组元素间的分隔符。在生成 CSV 文件的时候,某个属性是数组,将其元素使用 array-delimiter 指定的字符拼接起来,在读入 neo4j 之后,该字段依然能被识别为数组。

=> quote

在 csv 文件中,某个字段的内容中出现了 delimiter,这会导致某一行列数增加,csv 格式就会出错。解决的办法是,将此字段使用 quote 括起来。括起来的内容,出现 delimiter 不会被解释为列分隔符。

因此这里的 quote 需要根据生成 CSV 时的设置来决定。

=> ignore-duplicate-nodes

是否忽略重复的节点,即 ID 重复的是否忽略,默认为 false。

=> ignore-missing-nodes

某个关系指定的节点不存在时,是否忽略该条关系。如果不忽略,就会报错。默认为 false,即不忽略。

其他技巧

在一台机器上启动多个实例

=> 1. 将 neo4j 拷贝一份

cp ./neo4j-community-3.4.0/ ./project/neo4j-community-3.4.0/

=> 2. 修改配置文件

修改端口至一个未使用的端口,参考前文 neo4j 数据库安装指南

vim ./project/neo4j-community-3.4.0/conf/neo4j.conf

=> 3. 配置环境变量

将环境变量 NEO4J_HOME 临时指向新的 neo4j 代码包的拷贝。因为在导入数据的时候,和启动 neo4j 的时候,需要使用此环境变量。

export NEO4J_HOME="path-to-neo4j-dir"

=> 4. 导入数据

=> 5. 启动

./neo4j-community-3.4.0/bin/neo4j start