摘要:Neo4j
,Python
Neo4j下载安装
在Ubuntu系统下联网直接使用curl下载压缩包
curl -O http://dist.neo4j.org/neo4j-community-3.4.5-unix.tar.gz
移动目录并解压
root@ubuntu:~# mv neo4j-community-3.4.5-unix.tar.gz /opt
root@ubuntu:/opt# tar -axvf neo4j-community-3.4.5-unix.tar.gz
修改配置文件
root@ubuntu:/opt/# cd neo4j-community-3.4.5/conf
root@ubuntu:/opt/neo4j-community-3.4.5/conf# vim neo4j.conf
对如下内容进行修改
# 修改第22行load csv时l路径,在前面加个#,可从任意路径读取文件
#dbms.directories.import=import
# 修改35行和36行,设置JVM初始堆内存和JVM最大堆内存
# 生产环境给的JVM最大堆内存越大越好,但是要小于机器的物理内存
dbms.memory.heap.initial_size=5g
dbms.memory.heap.max_size=10g
# 修改46行,可以认为这个是缓存,如果机器配置高,这个越大越好
dbms.memory.pagecache.size=10g
# 修改54行,去掉改行的#,可以远程通过ip访问neo4j数据库
dbms.connectors.default_listen_address=0.0.0.0
# 默认 bolt端口是7687,http端口是7474,https关口是7473,不修改下面3项也可以
# 修改71行,去掉#,设置http端口为7687,端口可以自定义,只要不和其他端口冲突就行
#dbms.connector.bolt.listen_address=:7687
# 修改75行,去掉#,设置http端口为7474,端口可以自定义,只要不和其他端口冲突就行
dbms.connector.http.listen_address=:7474
# 修改79行,去掉#,设置https端口为7473,端口可以自定义,只要不和其他端口冲突就行
dbms.connector.https.listen_address=:7473
# 修改227行,去掉#,允许从远程url来load csv
dbms.security.allow_csv_import_from_file_urls=true
# 修改246行,允许使用neo4j-shell,类似于mysql 命令行之类的
dbms.shell.enabled=true
# 修改235行,去掉#,设置连接neo4j-shell的端口,一般都是localhost或者127.0.0.1,这样安全,其他地址的话,一般使用https就行
dbms.shell.host=127.0.0.1
# 修改250行,去掉#,设置neo4j-shell端口,端口可以自定义,只要不和其他端口冲突就行
dbms.shell.port=1337
# 修改254行,设置neo4j可读可写
dbms.read_only=false
添加neo4j环境变量
root@ubuntu:/opt/neo4j-community-3.4.5/conf# vim ~/.bashrc
export PATH=$PATH:/opt/neo4j-community-3.4.5/bin
root@ubuntu:/opt/neo4j-community-3.4.5/conf# source ~/.bashrc
启动,停止,查看neo4j服务
root@ubuntu:~# neo4j start
Active database: graph.db
Directories in use:
home: /opt/neo4j-community-3.4.5
config: /opt/neo4j-community-3.4.5/conf
logs: /opt/neo4j-community-3.4.5/logs
plugins: /opt/neo4j-community-3.4.5/plugins
import: NOT SET
data: /opt/neo4j-community-3.4.5/data
certificates: /opt/neo4j-community-3.4.5/certificates
run: /opt/neo4j-community-3.4.5/run
Starting Neo4j.
WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual.
Started neo4j (pid 26458). It is available at http://0.0.0.0:7474/
There may be a short delay until the server is ready.
See /opt/neo4j-community-3.4.5/logs/neo4j.log for current status.
root@ubuntu:~# neo4j status
Neo4j is running at pid 26458
root@ubuntu:~# neo4j stop
Stopping Neo4j.. stopped
root@ubuntu:~#
查看Web客户端打开http://0.0.0.0:7474/
,配置文件中默认的http端口号是7474,第一次访问账号neo4j,密码neo4j,会提示修改初始密码
在Web客户端退出已经登陆的用户在命令区输入:server disconnect
即可退出用户重新登陆
Web客户端使用
neo4j使用Web客户端作为管理平台,分为三个功能区,命令输入区
,状态工具栏
,结果显示区
,在命令输入区需要输入Cypher语句进行图数据库的增删改查操作,下面先创建数据,并实现数据检索
(1)创建图数据
使用CREATE
语句创建节点和关系,其中n:Person冒号后面的代表节点的标签,后面的Map代表节点的属性
CREATE (n:Person {name: '关羽', power: '蜀', force: 98})
CREATE (n:Person {name:'刘备', power: '蜀汉', force: 78})
CREATE (n:Person {name:'吕蒙', power: '孙吴', force: 76})
CREATE (n:Power {name:'蜀汉'})
CREATE (n:Person {name:'周瑜', power: '孙吴', force: 64})
此时通过MATCH语句返回所有的节点
MATCH (n) RETURN n
下一步创建关系,通过MATCH
模式匹配到对应的节点对,为节点对通过CREATE
创建关系,关系使用-
表示,对于指向的第二个节点对象,使用->
代表方向,neo4j在创建关系的时候必须指定方向,在检索关系的时候可以使用无向
MATCH ( a: Person ), ( b: Person )
WHERE a.name = "关羽" AND b.name = "刘备"
CREATE ( a )-[ r: brother ]->( b )
RETURN a, b;
也可以给关系添加属性
MATCH ( a: Person ), ( b: Power )
WHERE a.name = "关羽" AND b.name = "蜀汉"
CREATE ( a )-[ r:role_in {name: '武将'} ]->( b )
RETURN a, b;
同理继续增加关系
MATCH ( a: Person ), ( b: Person )
WHERE a.name = "吕蒙" AND b.name = "关羽"
CREATE ( a )-[ r: beat ]->( b )
RETURN a, b;
MATCH ( a: Person ), ( b: Person )
WHERE a.name = "吕蒙" AND b.name = "周瑜"
CREATE ( a )-[ r: colleagues ]->( b )
RETURN a, b;
通过MATCH显示全部节点如下
(2)检索节点
检索节点可以直接用MATCH
和结合WHERE
语句,比如name是关羽的节点
MATCH (a: Person {name: '关羽'}) RETURN a
也可以使用WHERE语句
MATCH (a: Person)
WHERE a.name = '关羽'
RETURN a
并且节点圆圈出现三个可以点击的功能,比如删除当前节点的可视化,拓展出节点的关系和子节点
同时在图片的下面看到一行节点的属性信息和标签信息
检索的呈现结果除了Graph,还有Table和Text,分别以JSON格式或者表格和文本格式呈现出检索结果
下一步可以使用Cypher语言检索多个节点,并且可以返回节点的属性信息,比如查找power属性是孙吴的Person的name信息
MATCH (a: Person)
WHERE a.power="孙吴"
RETURN a.name
返回结果如下,此时由于直接返回字符串而不是节点所以没有Graph呈现方式了
(3)查询关系
查询蜀汉和对应武将的归属关系,先再增加一条蜀国和刘备的关系
MATCH (a: Person), (b: Power)
WHERE a.name="刘备" and b.name="蜀汉"
CREATE (a) -[r:role_in {name:"君主"}]-> (b)
RETURN a, b
开始检索蜀国的武将和蜀国的关系
MATCH (a: Person) -[r:role_in]-> (b:Power) RETURN a, b
查看谁击败了关羽
MATCH (a: Person) -[r:beat]-> (b:Person)
WHERE b.name = "关羽"
RETURN a.name
如果仅仅是和关羽有关联,可以不指定关系标签,可以返回所有和关羽有关联的节点
MATCH (a: Person) -[]-> (b)
WHERE a.name = "关羽"
RETURN a, b;
在检索关系的时候可以不指定方向,此时第二个节点的箭头
->
改为-
即可,比如同样是检索和刘备有关系的节点和关系,先指定方向,此时刘备必须为出节点
MATCH (a: Person) -[]-> (b)
WHERE a.name = "刘备"
RETURN a, b;
再指定无向,此时刘备可以为出入任意节点,结果就比指定有向的多
MATCH (a: Person) -[]- (b)
WHERE a.name = "刘备"
RETURN a, b;
(4)其它常用的查询
通过Web客户端的命令窗口查询所有节点的标签种类,使用ALL db.labels()
命令
查看总共有多少中关系标签,使用
CALL db.relationshipTypes()
命令
查看索引,使用
CALL db.indexes()
查看有多少节点,使用count
方法
neo4j-shell使用
neo4j-shell是自带的命令行工具,可以运行命令返回结果,ubuntu下直接启动neo4j-shell即可
root@ubuntu:~# neo4j-shell
Welcome to the Neo4j Shell! Enter 'help' for a list of commands. Please note that neo4j-shell is deprecated and to be replaced by cypher-shell.
NOTE: Remote Neo4j graph database service 'shell' at port 1337
neo4j-sh (?)$
输入Cypher语句,结果以二维表的Table格式显示,如果返回节点则呈现出来的是Node信息属性,如果返回的具体的值则返回属性表头和属性值,除此之外返回查询响应时间
neo4j-sh (?)$ MATCH (n) RETURN n.name;
+--------+
| n.name |
+--------+
| "关羽" |
| "周瑜" |
| "刘备" |
| "吕蒙" |
| "蜀汉" |
+--------+
5 rows
84 ms
neo4j-sh (?)$ MATCH (n) RETURN n;
+-----------------------------------------+
| n |
+-----------------------------------------+
| Node[0]{name:"关羽",power:"蜀",force:98} |
| Node[1]{force:64,name:"周瑜",power:"孙吴"} |
| Node[20]{force:78,name:"刘备",power:"蜀汉"} |
| Node[21]{force:76,name:"吕蒙",power:"孙吴"} |
| Node[22]{name:"蜀汉"} |
+-----------------------------------------+
5 rows
52 ms
neo4j-shell可以换行,最终以分号;
作为结尾标志语句结束开始执行,退出neo4j-shell输入exit,不需要分号结束
Python操作neo4j
Python使用py2neo
操作neo4j,首先安装
root@ubuntu~# pip install py2neo
建立链接,输入http url以及认证用户名和密码
from py2neo import Graph
graph = Graph("http://0.0.0.0:7474", auth=("neo4j", "123456"))
可以直接使用run
方法运行Cypher语句,得到和neo4j-shell一样的效果
res = graph.run(
"""
MATCH (a: Person)
WHERE a.power="孙吴"
RETURN a.name
""")
结果可以使用data()
,to_ndarray()
,evaluate()
收集起来,分别输出为list,numpy.ndarray,纯值(第一个值)格式,分别输出如下
print(res.data())
[{'a.name': '周瑜'}, {'a.name': '吕蒙'}]
print(res.to_ndarray())
[['周瑜']
['吕蒙']]
print(res.evaluate())
周瑜
也可以不使用Cypher使用py2neo自己的API实现操作,主要有
-
NodeMatcher
,NodeMatch
:对节点进行匹配,检索节点,分别使用match
和where
进行检索 -
RelationshipMatcher
,RelationshipMatch
:对关系进行匹配,检索关系和节点,分别使用match
和where
进行检索
使用NodeMatcher的match方法进行检索,检索标签是Person,且属性中name是关羽的节点,结果只去第一个first,遍历属性使用items()
方法
from py2neo import Graph
from py2neo.matching import NodeMatcher
graph = Graph("http://0.0.0.0:7474", auth=("neo4j", "gp123456"))
nodes = NodeMatcher(graph)
res = nodes.match("Person", name="关羽").first()
# 也可以在match后面调用where
# nodes.match("Person").where(name="关羽").all()
for k, v in res.items():
print(k, v)
name 关羽
force 98
power 蜀
返回节点有多个的情况下,调用count()
查看节点数,调用all()
方法遍历出所有节点
res = nodes.match("Person", power="孙吴")
print(len(res)) # 匹配到的节点数
print(res.count()) # 匹配到的节点数
# 遍历
for node in res.all():
print("==========")
for k, v in node.items():
print(k, v)
2
2
==========
name 周瑜
force 64
power 孙吴
==========
name 吕蒙
force 76
power 孙吴
可以调用exists
方法查看检索语句是否有返回值,即是否为空
nodes = NodeMatcher(graph)
nodes.match("Person").where(name="关羽").exists() # True
nodes.match("Person").where(name="关羽", age=3).exists() # False
也可以使用NodeMatch
,使用where方法进行匹配,使用示例如下
from py2neo.matching import NodeMatch
graph = Graph("http://0.0.0.0:7474", auth=("neo4j", "gp123456"))
nodes = NodeMatch(graph)
nodes.where(name="关羽").first()
Node('Person', force=98, name='关羽', power='蜀')
下面测试RelationshipMatcher,并对匹配到的结果做进一步信息提取,RelationshipMatcher需要指定节点对,关系标签,属性等
from py2neo.matching import RelationshipMatcher
from py2neo import Graph
graph = Graph("http://0.0.0.0:7474", auth=("neo4j", "gp123456"))
nodes = NodeMatcher(graph)
Relationships = RelationshipMatcher(graph)
# 先匹配图上一个节点作为RelationshipMatcher的节点入参,在r_type可以加入更多属性
res = Relationships.match((nodes.match("Person").where(name="关羽").first(), ), r_type="role_in").all()
# [role_in(Node('Person', force=98, name='关羽', power='蜀'), Node('Power', name='蜀汉'), name='武将')]
# 提取关系属性
res[0].get("name") # 武将 只有name一个属性
res[0].nodes # 提取节点 (Node('Person', force=98, name='关羽', power='蜀'), Node('Power', name='蜀汉'))
res[0].nodes[0].get("name") # 关羽 提取节点属性
res[0].nodes[0]._labels # {'Person'} 提取节点的标签