目录
一、 Neo4j 介绍
- Neo4j是由Java实现的开源NoSQL图数据库. 自从2003年开始研发, 到2007年发布第一版. neo4j现如今已经被各行各业的数十万家公司和组织采用.
- Neo4j实现了专业数据库级别的图数据模型的存储. 与普通的图处理或内存级数据库不同, neo4j提供了完整的数据库特性, 包括ACID事物的支持, 集群支持, 备份与故障转移等. 这使其适合于企业级生产环境下的各种应用.
- Neo4j的版本说明:
- 企业版: 需要高额的付费获得授权, 提供高可用, 集群部署,热备份等性能.
- 社区开源版: 免费使用, 不能创建数据库,可以用默认数据库,但只能单点运行.
二、 Neo4j 图数据库概念
节点
- 节点是主要的数据元素, 节点通过关系连接到其他节点, 节点可以具有一个或多个属性 (即存储为键/值对的属性), 节点有一个或多个标签, 用于描述其在图表中的作用. 示例: Person>节点.
- 可以将节点类比为关系型数据库中的表, 对应的标签可以类比为不同的表名, 属性就是表中的列.
关系
- 关系连接两个节点, 关系是方向性的, 关系可以有一个或多个属性(即存储为键/值对的 属性).
属性
- 属性是命名值, 其中名称(或键)是字符串, 属性可以被索引和约束, 可以从多个属性创 建复合索引.
标签
- 标签用于组节点到集, 节点可以具有多个标签, 对标签进行索引以加速在图中查找节点
三、 Neo4j 图数据库的安装
这里主要介绍windows下Neo4j图数据库是如何安装的
Neo4j依赖java,所以我们会进行以下操作
JDK安装
Neo4j安装
以下是Neo4j与JVM版本要求
https://neo4j.com/docs/operations-manual/current/installation/requirements/
3.1 JAVA安装
- 第一步: 安装JAVA SE 的 JDK
- 下载地址: https://www.oracle.com/java/technologies/downloads/#java11 (注意: 在点击下载的过程中, 可能需要需要oracle账户, 直接注册登录即可下载)
- 下载安装完之后, 打开windows终端, 输入java --version检查是否安装好
3.2 Neo4j安装
第二步: 下载安装Neo4j
从官网下载社区版本, 下载地址: https://neo4j.com/download-center/#community
https://neo4j.com/product/developer-tools/
这里注意, 因为JDK为11版本, 所以我们这里对应下载Neo4j 4.x版本
- 下载好后, 解压到自己想放的盘里(注意, 路径不要出现中文, 以免报错). 例如: C:\Program Files (x86)\neo4j-community-4.4.41
- 第三步: 对Neo4j进行环境变量配置
创建系统环境变量
- 过程: 电脑--->属性--->高级系统设置--->环境变量--->新建
- 手动添加变量名称和变量值(注意变量值是你存放文件的路径)
- 在path路径中将变量添加进去
第四步: 启动neo4j数据库
- 打开cmd, 输入: neo4j console
- http://localhost:7474/ 浏览器地址
浏览器页面展示
注意: 如果你是第一次安装登录成功, 需要输入用户名和密码(默认用户名和密码一致都是: neo4j). 第一次登录需要更改密码. (我的改为:itcast,登录名:neo4j)
更改密码:
3.3 界面介绍
①数据库
②收藏
③浏览器指南
④帮助
一些帮助文档和最开始尝试的资源。最开始学可以从这里进入。还有一些常用的命令他都给你列出来了,对新手还是挺友好的。
⑤浏览器同步
Neo4j Browser Sync是一个配套 Neo4j Browser 的服务,允许用户通过社交账号登录(登录)或注册(注册),方便在不同设备或会话之间同步和保存 Neo4j Browser 的设置和数据。
⑥浏览器设置
⑦关于neo4j
为什么会有上下两个 命令行?
四、 Cypher介绍与使用
图数据库基础check:小试牛刀
#查询数据库所有节点
MATCH (n) return n
#统计所有节点个数
MATCH (n)
RETURN count(n) AS totalNodeCount
#清除所有节点
MATCH (n)
DETACH DELETE n
#查询所有关系
MATCH ()-[r]->()
RETURN r
#统计所有关系
MATCH ()-[r]->()
RETURN count(r) AS relationshipCount
#显示所有的属性key
CALL db.propertyKeys()
4.1 create命令
- 创建图数据中的节点
- 演示:
# 创建命令格式:
# 此处create是关键字, 创建节点名称node_name, 节点标签Node_Label, 放在小括号里面()
# 后面把所有属于节点标签的属性放在大括号'{}'里面, 依次写出属性名称: 属性值, 不同属性用逗号','分隔
# 例如下面命令创建一个节点e, 节点标签是Employee, 拥有id, name, salary, deptnp四个属性:
CREATE (e:Employee{id:222, name:'Bob', salary:6000, deptnp:12})
- 效果
关于e:
e是执行语句时的临时变量,执行结束后,就无效了。
如果我们重复多次创建CREATE (e:Employee)也是可以的,系统会创建多个,但是neo4j系统内部会为每个节点产生一个内部id,进行节点的管理。
#创建一个没有任何属性名字的节点,没哟id返回
CREATE (e:Employee)
#创建节点的同时,返回id
CREATE (e:Employee) RETURN e, id(e) AS internalId
#自定义id,同时返回系统id
CREATE (e:Employee{id:"dt13",name:'xiaoli'}) RETURN e, id(e) AS internalId
MATCH (n:Employee) WHERE id(n) = 180 RETURN n, id(n) AS internalId
创建一个id已经存在节点:
这里的elementid与id,都是系统内部生成的。实际业务,建议自定义id,进行自行管理
CREATE (e:Employee{id:178})RETURN e, id(e) AS internalId
4.2 match命令
- 匹配(查询)已有数据
- 演示:
# match命令专门用来匹配查询, 节点名称: 节点标签, 依然放在小括号内, 然后使用return语句返回查询结果, 和SQL很相似.
MATCH (e:Employee) RETURN e.id, e.name, e.salary, e.deptno
MATCH (n) return n # 查询所有结点
- 效果
4.3 merge命令
- 若节点存在, 则等效与match命令; 节点不存在, 则等效于create命令.
- 演示:
MERGE (e:Employee {id:146, name:'Lucer', salary:3500, deptno:16})
- 效果:
- 然后再次用merge查询, 发现数据库中的数据并没有增加, 因为已经存在相同的数据了, merge匹配成功.
- 演示:
#注意查看内部id
MERGE (e:Employee {id:146, name:'Lucer', salary:3500, deptno:16})
#查询内部系统id
MATCH (n:Employee) WHERE id(n) = 146 RETURN n, id(n) AS internalId
- 效果:
#查询自定义id
MERGE (e:Employee {id: 146, name: 'Lucer', salary: 3500, deptno: 16})
RETURN id(e)
效果:
4.4 使用create创建关系
- 必须创建有方向性的关系, 否则报错.
- 演示:
# 创建一个节点p1到p2的有方向关系, 这个关系r的标签为Buy, 代表p1购买了p2, 方向为p1指向p2
CREATE (p1:Profile1)-[r:Buy]->(p2:Profile2)
- 效果:
4.5 使用merge创建关系
- 可以创建有/无方向性的关系.
- 演示:
# 创建一个节点p1到p2的无方向关系, 这个关系r的标签为miss, 代表p1-miss-p2, 方向为相互的
MERGE (p1:Profile1)-[r:miss]-(p2:Profile2)
- 效果:
双向关系
#一次性执行
MATCH (alice:Person {name: 'Alice'}), (bob:Person {name: 'Bob'})
CREATE (alice)-[:FRIEND_OF]->(bob)
CREATE (bob)-[:FRIEND_OF]->(alice)
#如果被分段执行了会怎么样?
会成为无节点无属性的实体(没有家的实体),所以我们的创建要更加规范化,否则时间长了都是无效数据。
CREATE (Bbob)-[:FRIEND_OF]->(Aalice)
4.6 where命令
- 类似于SQL中的添加查询条件.
- 演示:
#创建一个节点
CREATE (e:Employee{id:222, name:'Bob', salary:6000, deptnp:12})
# 查询节点Employee中, id值等于123的那个节点
MATCH (e:Employee) WHERE e.id=222 RETURN e
- 效果:
4.7 delete命令
- 删除节点/关系及其关联的属性.
- 演示:
#创建关系
CREATE (p1:Profile1)-[r:Buy]->(p2:Profile2)
# 注意: 删除节点的同时, 也要删除关联的关系边
MATCH (p1:Profile1)-[r]-(p2:Profile2) DELETE p1, r, p2
- 效果:
4.8 sort命令
- Cypher命令中的排序使用的是order by.
- 演示:
# 匹配查询标签Employee, 将所有匹配结果按照id值升序排列后返回结果
MATCH (e:Employee) RETURN e.id, e.name, e.salary, e.deptno ORDER BY e.id
# 如果要按照降序排序, 只需要将ORDER BY e.salary改写为ORDER BY e.salary DESC
MATCH (e:Employee) RETURN e.id, e.name, e.salary, e.deptno ORDER BY e.salary DESC
- 效果:
4.9 字符串函数:
创建:
CREATE (e:Employee{id:111, name:'jack', salary:16000, deptnp:2111})
CREATE (e:Employee{id:221, name:'ALICE', salary:17000, deptnp:988})
toUpper()函数
- 将一个输入字符串转换为大写字母.
- 演示:
#match还没有转换
MATCH (e:Employee) where e.id=111 RETURN e
#match转换之后
MATCH (e:Employee) where e.id=111 RETURN e.id, toUpper(e.name), e.salary, e.deptno
#match转换之后的
MATCH (e:Employee) where e.id=111 RETURN e
#将转换结果更新到原有节点
MATCH (e:Employee)
WHERE e.id = 111
SET e.name = toUpper(e.name)
RETURN e.id, e.name, e.salary, e.deptno
#查看转换更新后的节点
MATCH (e:Employee) where e.id=111 RETURN e
- 效果:
toLower()函数
- 将一个输入字符串转换为小写字母.
- 演示:
MATCH (e:Employee) RETURN e.id, toLower(e.name), e.salary, e.deptno
- 效果:
substring()函数
- 返回一个子字符串.
- 演示:
# 输入字符串为input_str, 返回从索引start_index开始, 到end_index-1结束的子字符串
substring(input_str, start_index, end_index)
# 示例代码, 返回员工名字的前两个字母
MATCH (e:Employee) RETURN e.id, substring(e.name,0,2), e.salary, e.deptno
- 效果:
4 replace()函数
- 替换掉子字符串.
- 演示:
# 输入字符串为input_str, 将输入字符串中符合origin_str的部分, 替换成new_str
replace(input_str, origin_str, new_str)
# 示例代码, 将员工名字替换为添加后缀_HelloWorld
MATCH (e:Employee) RETURN e.id, replace(e.name,e.name,e.name + "_HelloWorld"), e.salary, e.deptno
# 还原
MATCH (e:Employee) RETURN e.id, replace(e.name, "_HelloWorld", ""), e.salary, e.deptno
- 效果:
五、 聚合函数
5.1 count()函数
- 返回由match命令匹配成功的条数.
- 演示:
# 返回匹配标签Employee成功的记录个数
MATCH (e:Employee) RETURN count( * )
- 效果:
5.2 max()函数
- 返回由match命令匹配成功的记录中的最大值.
- 演示:
# 返回匹配标签Employee成功的记录中, 最高的工资数字
MATCH (e:Employee) RETURN max(e.salary)
- 效果:
5.3 min()函数
- 返回由match命令匹配成功的记录中的最小值.
- 演示:
# 返回匹配标签Employee成功的记录中, 最低的工资数字
MATCH (e:Employee) RETURN min(e.salary)
- 效果:
5.4 sum()函数
- 返回由match命令匹配成功的记录中某字段的全部加和值.
- 演示:
# 返回匹配标签Employee成功的记录中, 所有员工工资的和
MATCH (e:Employee) RETURN sum(e.salary)
- 效果:
5.5 avg()函数
- 返回由match命令匹配成功的记录中某字段的平均值.
- 演示:
# 返回匹配标签Employee成功的记录中, 所有员工工资的平均值
MATCH (e:Employee) RETURN avg(e.salary)
- 效果:
六、 索引index
- Neo4j支持在节点或关系属性上的索引, 以提高查询的性能.
可以为具有相同标签名称的所有节点的属性创建索引.
无索引:Neo4j会扫描所有Employee节点,检查每个节点的id是否等于111,时间复杂度为O(n)。
有索引:Neo4j使用B+树或哈希索引直接定位id = 111的节点,时间复杂度接近O(log n),性能大幅提高。
#索引查询:
CALL db.indexes()
6.0 如何确认查询是否使用了索引
#构造900多样本数据。UNWIND用于展开一个列表或范围,并为每个元素分配一个变量
UNWIND range(112, 1012) AS i
CREATE (e:Employee {id: i, name: "Employee" + i})
#基于没有建立索引的情况下进行查询
PROFILE MATCH (e:Employee)
WHERE e.id = 122
RETURN e
6.1 创建索引
- 使用create index on来创建索引.
- 演示:
# 创建节点Employee上面属性id的索引,对Employee整个节点标签的实体进行构建索引:
CREATE INDEX ON:Employee(id)
- 效果:
6.2 索引查询
#基于没有建立索引的情况下进行查询
PROFILE MATCH (e:Employee)
WHERE e.id = 122
RETURN e
NodeIndexSeek 替代了之前的 NodeByLabelScan,证明 CREATE INDEX ON:Employee(id) ON (e.id) 已生效。
DB Hits 从之前的 904 (扫描) + 903 (过滤) + 3 = 1810 降至 2 + 3 = 5,性能显著提升。
#增加百万数据可以自己自己测一下
UNWIND range(1013, 1001012) AS i
CREATE (e:Employee {id: i, name: "Employee" + i})
6.3 删除索引
- 使用drop index on来删除索引.
- 演示:
# 删除节点Employee上面属性id的索引
DROP INDEX ON:Employee(id)
- 效果:
七、 数据库服务器版本
检查Neo4j服务器版本:
CALL dbms.components()
八、 密码忘记或者用不了
遇到如下问题:
The client is unauthorized due to authentication failure.
或者
Neo.ClientError.Security.Unauthorized: The client is unauthorized due to authentication failure.
解决:在C:\neo4j-community-4.4.41\conf中的neo4j.conf找到dbms.security.auth_enabled=false。设置如下: