Neo4j
为多种语言提供了 API 接口,如 java
,python
,C#
,RUBY
,.NET
等。本文首先介绍用 python
操作 Neo4j。
首先安装好py2neo库
sudo pip3 install py2neo
1. 连接数据库
from py2neo import Graph
# 连接本地的 Neo4j 数据库,地址为 127.0.0.1,http 端口默认为 7474,用户名和密码分别为 neo4j 与 123
graph = Graph(host='127.0.0.1', http_port=7474, user='neo4j', password='123')
2. 创建节点
from py2neo import Node
# 创建角色节点 郭靖,拥有属性 姓名-郭靖,性别-男
guojing = Node('角色',name='郭靖',sex='男')
3. 操作属性
# 获取key对应的属性
guojing['name']
# 设置 key 对应属性的value,如果key不存在就创建
huangrong['born'] = '桃花岛'
# 删除某个属性
del huangrong['born']
# 返回节点中 property 的个数
len(huangrong)
# 此时的节点已经创建在本地,但还没有上传到 Neo4j 数据库中,因此在 Neo4j 客户端中是没有任何内容的,所以接下来使用 Graph 中的 create 方法来上传数据。
graph.create(guojing)
在这里,如果重复 create
同一个节点,如
# 反复执行此命令来创建郭靖节点
graph.create(guojing)
# 重新 guojing 变量赋值
guojing = Node('角色',name='郭靖',sex='男')
guojing
实际上在 Neo4j
数据库中并不会重复创建,因为在上传 guojing
节点时,变量的 <id>
属性已经固定,所以不会重复。如果重新定义一个 guojing
节点。节点前的 <id>
属性被抹去,此时在上传,数据库中就会存在两个相同节点了,若要避免这种情况,就需要用到 Graph
中的 merge
方法了。
关系的操作和节点操作很类似:
4. 创建关系
from py2neo import Relationship
# 创建郭靖与黄蓉的配偶关系
spouse1 = Relationship(guojing,'配偶',huangrong)
# 创建黄蓉与郭靖的配偶关系
spouse2 = Relationship(huangrong,'配偶',guojing)
# 创建郭靖与射雕英雄传的所在作品关系
inbook1 = Relationship(guojing,'所在作品',shediao)
# 创建黄蓉与射雕英雄传的所在作品关系
inbook2 = Relationship(huangrong,'所在作品',shediao)
# 打印结果
spouse1,spouse2,inbook1,inbook2
# 设置 key 对应属性的 value
inbook1['role'] = '男主角'
# 删除某个属性
del inbook1['role']
# 创建黄蓉与射雕英雄传的所在作品关系
graph.create(inbook2)
5. 查找
from py2neo import NodeMatcher
# 初始化一个 matcher 实例
matcher = NodeMatcher(graph)
# 用 match 方法查找 角色中name为郭靖的节点,返回一个 NodeMatch 对象
result = matcher.match("角色", name="郭靖")
# first 方法返回查询结果的第一个
result.first()
# 通过 list 来把所有结果显示出来
list(result)
Graph
同时提供 run
方法来直接执行 Cypher
语句。
# cypher 语句,对已存在的郭靖节点,创建节点和关系 (郭靖)-[父]->(郭啸天)
query = "match (n) where n.name = '郭靖' create (n)-[:父]->(:角色{name:'郭啸天'})"
# 执行 cypher 语句
graph.run(query)
# run 方法返回的是游标 cursors,cursors 必须通过遍历来展示结果
# cypher 语句,查询并返回所有的节点
query = "match (n) return n"
# 执行 cypher 语句,获得返回结果
cursors = graph.run(query)
# 通过遍历的方式取出所有结果
for i in cursors:
print(i)
以上讲述了 Neo4j
数据库的 python
驱动 py2neo
的基本使用方法,在实际应用中,由于 python
胶水语言的特性,py2neo
可以搭配其他库方便地对知识图谱进行创建。比如在数据集中存在重复数据的情况,可以先用 python
进行一遍去重,再提交,比用 Cypher
语言去重速度更快。然而需要向数据库中写入大量数据时,用 CREATE
一条一条创建是非常低效的,因此,下面将介绍如何批量导入数据。
常见导入方法总结如下表:
CREATE 语句 | LOAD CSV 语句 | Batch Inserter | Batch Import | Neo4j-admin import | |
---|---|---|---|---|---|
适用场景 | 1 ~ 1 w nodes | 1 w ~ 10 w nodes | 千万以上 nodes | 千万以上 nodes | 千万以上 nodes |
速度 | 1000 nodes/s | 5000 nodes/s | 数万 nodes/s | 数万 nodes/s | 数万 nodes/s |
优点 | 使用方便,可实时插入 | 使用方便,可加载本地和远程 CSV;可实时插入 | 速度相比于前两个有数量级的提升 | 基于 Batch Inserter,可直接运行编译好的 jar 包,可以在已存在的数据库中导入数据 | 比 Batch Import 占用更少的资源 |
缺点 | 速度慢 | 需要将数据转换成 CSV | 需要转成 CSV;只能在 JAVA 中使用;必须停止 Neo4j | 需转成 CSV;必须停止 Neo4j | 需要转成 CSV;必须停止 Neo4j;只能生成新的数据库,而不能在已存在的数据库中插入数据 |
这里重点介绍neo4j-admin import 构建,Neo4j 官方提供了 neo4j-admin import
来解决数据量非常大时导入的性能瓶颈。
参数设置如下:
- --nodes 节点所在 CSV 文件
- --relationships 关系所在 CSV 文件
nodes 节点所在 CSV 文件格式形式如下
第一列为 ID 号,在构建关系时必须用过 ID 号来对应关系,第二、三列为属性值,第四列为节点类型。
relationships 关系所在 CSV 文件格式形式如下
第一列表示起始节点的 ID 号,第二列表示截至节点的 ID 号,第三列为关系类型。
在使用 neo4j-admin import
时,需要先 sudo neo4j stop
停止 Neo4j 服务,同时删除旧的 graph.db 文件(通过 neo4j.conf
可以知道在 /var/lib/neo4j/data/databases
目录下)。
$ ./neo4j-admin import --nodes=../import/nodes.csv --relationships=../import/relationships.csv