目录
Neo4j 基础
什么是Neo4j
Neo4j 模块构建
Neo4j的主要应用场景
Neo4j 环境搭建
Docker 安装Neo4j
Neo4j数据浏览器
Neo4j CQL
CQL简介
Neo4j CQL高级
CQL 函数
CQL多深度关系节点
事务
索引
约束
Neo4j之Admin管理员操作
Neo4j - 数据库备份和恢复
调优思路
Neo4j 程序访问
SpringBoot 整合Neo4j
Neo4j是一个开源的 无Shcema的 基于java开发的 图形数据库,它将结构化数据存储在图中而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎。程序数据是在一个面向对象的、灵活的网络结构下,而不是严格、静态的表中,但可以享受到具备完全的事务特性、企业级的数据库的所有好处。
https://db-engines.com/en/ranking
Neo4j 主要构建块
节点
节点是图表的基本单位。 它包含具有键值对的属性
属性
属性是用于描述图节点和关系的键值对
Key =值
其中Key是一个字符串
值可以通过使用任何Neo4j数据类型来表示
关系
关系是图形数据库的另一个主要构建块。 它连接两个节点,如下所示。
这里Emp和Dept是两个不同的节点。 “WORKS_FOR”是Emp和Dept节点之间的关系。
因为它表示从Emp到Dept的箭头标记,那么这种关系描述的一样
Emp WORKS_FOR Dept
每个关系包含一个起始节点和一个结束节点。
这里“Emp”是一个起始节点。
“Dept”是端节点。
由于该关系箭头标记表示从“Emp”节点到“Dept”节点的关系,该关系被称为“进入关系”到“Dept”节点。
并且“外向关系”到“Emp”节点。
像节点一样,关系也可以包含属性作为键值对。
标签
Label将一个公共名称与一组节点或关系相关联。 节点或关系可以包含一个或多个标签。 我们可以为现
有节点或关系创建新标签。 我们可以从现有节点或关系中删除现有标签。
从前面的图中,我们可以观察到有两个节点。
左侧节点都有一个标签:“EMP”,而右侧节点都有一个标签:“Dept”。
这两个节点之间的关系,也有一个标签:“WORKS_FOR”
注: -Neo4j将数据存储在节点或关系的属性中。
社交媒体和社交网络
当使用图形数据库为社交网络应用程序提供动力时,可以轻松利用社交关系或根据活动推断关系。
查询社区聚类分析,朋友的朋友推荐,影响者分析,共享和协作关系分析等
推荐引擎和产品推荐系统
图形驱动的推荐引擎通过实时利用多种连接,帮助公司个性化产品,内容和服务。
内容和媒体推荐,图形辅助搜索引擎,产品推荐,专业网络,社会推荐。
身份和访问管理
使用图形数据库进行身份和访问管理时,可以快速有效地跟踪用户,资产,关系和授权。
查询访问管理,资产来源,数据所有权,身份管理,互连组织,主数据,资源授权
金融反欺诈多维关联分析场景
通过图分析可以清楚地知道洗钱网络及相关嫌疑,例如对用户所使用的帐号、发生交易时的IP地址、MAC地址、手机IMEI号等进行关联分析。
Neo4j环境Linux下搭建
(1).切换到Linux下 到安装目录neo4j 上传安装包 或者 下载安装包
使用 ftp 工具上传neo4j-community-3.5.17.tar 到 liunx 下
或者 wget https://neo4j.com/artifact.php?name=neo4j-community-3.5.17-unix.tar.gz
(2). 解压
tar -xvf neo4j-community-3.5.17.tar
(3). 修改配置文件 neo4j.conf
vi conf/neo4j.conf
主要是修改 允许远程访问的地址 把对应的注释打开即可
dbms.connectors.default_listen_address=0.0.0.0
(4).开放对应的访问端口 默认要开放7474 和 7687
fifirewall-cmd --zone=public --add-port=7474/tcp --permanent
fifirewall-cmd --zone=public --add-port=7687/tcp --permanent
systemctl reload fifirewalld
(5).启动
./bin/neo4j start
(6).使用浏览器 访问服务器上的 neo4j
http://192.168.8.128:7474
默认的账号是 neo4j 密码 neo4j 这里第一次登录的话会要求修改密码
1.拉取Neo4j镜像
docker pull neo4j
2. 简单运行Neo4j
docker run -d --name neo4j -p 7474:7474 -p 7687:7687 neo4j
3.查看日志是否启动成功
docker logs -f neo4j
4.访问数据浏览器查看是否成功
http://192.168.8.128:7474/browser
如需挂载目录:
docker run -d --name container_name \ //-d表示容器后台运行 --name指定容器名字
-p 7474:7474 -p 7687:7687 \ //映射容器的端口号到宿主机的端口号
-v /home/neo4j/data:/data \ //把容器内的数据目录挂载到宿主机的对应目录下
-v /home/neo4j/logs:/logs \ //挂载日志目录
-v /home/neo4j/conf:/var/lib/neo4j/conf //挂载配置目录
-v /home/neo4j/import:/var/lib/neo4j/import \ //挂载数据导入目录
--env NEO4J_AUTH=neo4j/password \ //设定数据库的名字的访问密码
neo4j //指定使用的镜像
数据浏览器访问
一旦我们安装Neo4j,我们可以访问Neo4j数据浏览器使用以下URL
http:// localhost:7474/browser/
Neo4j数据浏览器用于执行CQL命令并查看输出输出。
这里我们需要在美元提示符处执行所有CQL命令:“$” 如 CREATE(cc:CreditCard)在美元符号后键入命令,然后单击“执行”按钮运行命令。
它与Neo4j数据库服务器交互,检索和显示下面的结果到那个美元提示。
使用“VI视图”按钮以图形格式查看结果。 上图以“UI视图”格式显示结果。
导出 CSV 或者 JSON
单击“导出CSV”按钮以csv文件格式导出结果
CQL代表Cypher查询语言。 像关系型数据库具有查询语言SQL,Neo4j使用CQL作为查询语言。
Neo4j CQL
常用的Neo4j CQL命令/条款如下:
S.No. |
CQL命令/条 |
作用 |
1 | CREATE 创建 |
创建节点,关系和属性 |
2 | MATCH 匹配 |
检索有关节点,关系和属性数据 |
3 | RETURN 返回 |
返回查询结果 |
4 | WHERE 条件 |
提供条件过滤检索MATCH数据 |
5 | DELETE 删除 |
删除节点和关系 |
6 | REMOVE 移除 |
删除节点和关系的属性 |
7 | SET 设置 |
添加或更新标签 |
8 | ORDER BY 排序 |
对结果排序 |
9 | SKIP LIMIT 分页 |
分页 |
10 | DISTINCT 排重 |
排重 |
CREATE
CREATE (
: [{
: ........
: }]
)
语法说明:
语法元素 | 描述 |
< node-name> | 它是我们将要创建的节点名称。 |
< label-name> | 它是一个节点标签名称 |
< property1-name>...< propertyn-name> |
属性是键值对。 定义将分配给创建节点的属性的名称 |
< property1-value>...< propertyn-value> |
属性是键值对。 定义将分配给创建节点的属性的值 |
举例:
CREATE (person:Person {cid:1,name:"小张",age:24,gender:0,character:"A",money:1000});
MATCH RETURN命令语法
MATCH
(
: )
RETURN
. , ...
.
语法元素 | 描述 |
< node-name> |
它是我们将要创建的节点名称。 |
< label-name> |
它是一个节点标签名称 |
< property1-name>...< propertyn-name> |
属性是键值对。 定义将分配给创建节点的属性的名称 |
举例:
MATCH (person:Person) return person
MATCH (person:Person) return person.name,person.age
关系创建
MATCH (
: ),( : ) CREATE
(
)-[ : ]->( name>)
RETURN 相应的内容
语法说明:
S.No. | 语法元素 | 描述 |
1 | MATCH,CREATE,RETURN | 他们是Neo4J CQL关键字。 |
2 | < noode1-name> | 它用于创建关系的“From Node”的名称。 |
3 | < node1-label-name> | 它用于创建关系的“From Node”的标签名称。 |
4 | < node2-name> | 它用于创建关系的“To Node”的名称。 |
5 | < node2-label-name> | 它用于创建关系的“To Node”的标签名称。 |
6 | < relationship-name> | 这是一个关系的名称。 |
7 | < relationship-label-name> | 它是一个关系的标签名称。 |
举例:
创建关系
match(person:Person {name:"小张"}) ,(person2:Person {name:"小林"}) create(person)-[r:Couple]->(person2);
查询关系
match p = (person:Person {name:"小张"})-[r:Couple]->(person2:Person) return p
match (p1:Person {name:"小张"})-[r:Couple]-(p2:Person) return p1,p2
match (p1:Person {name:"小张"})-[r:Couple]-(p2:Person) return r
MATCH (
: ),( : ) CREATE
(
)-[ : {
}]->( ) RETURN
其中
是分配给新创建关系的属性(名称 - 值对)的列表。 {
: ,
: , ...
: }
举例:
match(person:Person {name:"小张"}),(person2:Person {name:"小林"})
create(person)-[r:Couple{mary_date:"12/12/2014",price:55000}]->(person2)
return r;
CREATE
(
: ) -[
: ]-> (
: )
举例:
create
(person1:Person {cid:4,name:"小王",age:49,gender:1,character:"A",money:5000})
-[r:Friend]->
(person2:Person{cid:7,name:"小刘",age:48,gender:0,character:"B",money:100})
CREATE
(
: { }) -[
: { }] ->(
: { })
举例:
create
(person1:Person {cid:9,name:"王武",age:23,gender:0,character:"A",money:3000})
<-[r:Friend {date:"11-02-2000"}]->
(person2:Person {cid:8,name:"赵六",age:24,gender:0,character:"B",money:6000})
关系和节点的属性可以使用的类型
Index | CQL数据类型 | 作用 |
1 | boolean | 它用于表示布尔文字:true, false。 |
2 | byte | 它用来表示8位整数。 |
3 | short | 它用于表示16位整数。 |
4 | int | 它用于表示32位整数 |
5 | Long | 它用于表示64位整数。 |
6 | float | 浮点数用于表示32位浮点数。 |
7 | double | Double用于表示64位浮点数。 |
8 | char | Char用于表示16位字符。 |
9 | String | 字符串用于表示字符串。 |
CREATE创建多个标签
CREATE (
: : .....: ) 如:
CREATE (person:Person:Beauty:Picture {cid:20,name:"小美女"})
WHERE 子句
简单的WHERE子句
WHERE
复杂的WHERE子句
WHERE
where 中的比较运算符 和 之前mysql的相同 如 = != <> > < 等
S.No. | 布尔运算符 | 描述 |
1 | AND | 与 |
2 | OR | 或 |
3 | NOT | 非 |
举例:
MATCH (person:Person)
WHERE person.name = '小张' OR person.name = '小王'
RETURN person
DELETE 子句 和 REMOVE子句
DELETE 子句
match p = (:Person {name:"小王"})-[r:Couple]-(:Person) delete r
REMOVE子句
MATCH (person:Person {name:"小美女"}) REMOVE person.cid
SET子句
MATCH (person:Person {cid:1})
SET person.money = 3456,person.age=25
ORDER BY 子句
“ORDER BY”子句,对MATCH查询返回的结果进行排序。
我们可以按升序或降序对行进行排序。
默认情况下,它按升序对行进行排序。 如果我们要按降序对它们进行排序,我们需要使用DESC子句。
MATCH (person:Person)
RETURN person.name,person.money
ORDER BY person.money DESC
SKIP 和 LIMIT
Neo4j CQL已提供“SKIP”子句来过滤或限制查询返回的行数。 它修整了CQL查询结果集顶部的结果。
Neo4j CQL已提供“LIMIT”子句来过滤或限制查询返回的行数。 它修剪CQL查询结果集底部的结果。
MATCH (person:Person)
RETURN ID(person),person.name,person.money
ORDER BY person.money DESC skip 4 limit 2
DISTINCT 排重
这个函数的用法就像SQL中的distinct关键字,返回的是所有不同值。
MATCH (p:Person) RETURN Distinct(p.character)
字符串函数
S.No. | 功能 | 描述 |
1 | UPPER | 它用于将所有字母更改为大写字母。 |
2 | LOWER | 它用于将所有字母改为小写字母。 |
3 | SUBSTRING | 它用于获取给定String的子字符串。 |
4 | REPLACE | 它用于替换一个字符串的子字符串。 |
举例:
MATCH (p:Person)
RETURN ID(p),LOWER(p.character)
match(p:Person) return
p.character,lower(p.character),p.name,substring(p.name,2),replace(p.name,"子","zi")
聚合函数
S.No. | 聚集功能 | 描述 |
1 | COUNT | 它返回由MATCH命令返回的行数。 |
2 | MAX | 它从MATCH命令返回的一组行返回最大值。 |
3 | MIN | 它返回由MATCH命令返回的一组行的最小值。 |
4 | SUM | 它返回由MATCH命令返回的所有行的求和值。 |
5 | AVG | 它返回由MATCH命令返回的所有行的平均值。 |
举例:
MATCH (p:Person)
RETURN MAX(p.money),SUM(p.money)
关系函数
S.No. | 聚集功能 | 描述 |
1 | STARTNODE | 它用于知道关系的开始节点。 |
2 | ENDNODE | 它用于知道关系的结束节点。 |
3 | ID | 它用于知道关系的ID |
4 | TYPE | 它用于知道字符串表示中的一个关系的TYPE。 |
举例:
match p = (:Person {name:"小王"})-[r:Couple]-(:Person)
RETURN STARTNODE(r)
shortestPath 函数返回最短的path
MATCH p=shortestPath( (node1)-[*]-(node2) )
RETURN length(p), nodes(p)
举例:
MATCH p=shortestPath((person:Person {name:"小王"})-[*]-(person2:Person
{name:"王武"}) ) RETURN length(p), nodes(p)
使用with关键字
查询三层级关系节点如下:with可以将前面查询结果作为后面查询条件
match (na:Person)-[re]->(nb:Person) where na.name="小张" WITH na,re,nb match (nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc
match (na:Person)-[re]->(nb:Person) where na.name="小林" WITH na,re,nb match (nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc
直接拼接关系节点查询
match (na:Person{name:"小张"})-[re]->(nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc
为了方便,可以将查询结果赋给变量,然后返回
match data=(na:Person{name:"小张"})-[re]->(nb:Person)-[re2]->(nc:Person) return data
使用深度运算符
当实现多深度关系节点查询时,显然使用以上方式比较繁琐。
可变数量的关系->节点可以使用-[:TYPE*minHops..maxHops]-。
查询:
match data=(na:Person{name:"小张"})-[*1..2]-(nb:Person) return data
为了保持数据的完整性和保证良好的事务行为,Neo4j也支持ACID特性 。
注意:
(1)所有对Neo4j数据库的数据修改操作都必须封装在事务里。
(2)默认的isolation level是READ_COMMITTED。
(3)死锁保护已经内置到核心事务管理 。 (Neo4j会在死锁发生之前检测死锁并抛出异常。在异常抛出之前,事务会被标志为回滚。当事务结束时,事务会释放它所持有的锁,则该事务的锁所引起的死锁也就是解除,其他事务就可以继续执行。当用户需要时,抛出异常的事务可以尝试重新执行)
(4)除特别说明,Neo4j的API的操作都是线程安全的,Neo4j数据库的操作也就没有必要使用外部的同步方法。
简介
Neo4j CQL支持节点或关系属性上的索引,以提高应用程序的性能。
可以为具有相同标签名称的属性上创建索引。
可以在MATCH或WHERE等运算符上使用这些索引列来改进CQL 的执行。
创建单一索引
CREATE INDEX ON :Label(property)
例如:
CREATE INDEX ON :Person(name)
创建复合索引
CREATE INDEX ON :Person(age, gender)
全文模式索引
之前的常规模式索引只能对字符串进行精确匹配或者前后缀索(startswith,endswith,contains),全文索引将标记化索引字符串值,因此它可以匹配字符串中任何位置的术语。索引字符串如何被标记化并分解为术语,取决于配置全文模式索引的分析器。索引是通过属性来创建,便于快速查找节点或者关系。
创建和配置全文模式索引
使用db.index.fulltext.createNodeIndex和db.index.fulltext.createRelationshipIndex创建全文模式索引。在创建索引时,每个索引必须为每个索引指定一个唯一的名称,用于在查询或删除索引时引用相关的特定索引。然后,全文模式索引分别应用于标签列表或关系类型列表,分别用于节点和关系索引,然后应用于属性名称列表。
call db.index.fulltext.createNodeIndex("索引名",[Label,Label],[属性,属性])
call db.index.fulltext.createNodeIndex("nameAndDescription",["Person"],["name",
"description"])
call db.index.fulltext.queryNodes("nameAndDescription", "小张") YIELD node, score
RETURN node.name, node.description, score
查看和删除索引
call db.indexes 或者 :schema
DROP INDEX ON :Person(name)
DROP INDEX ON :Person(age, gender)
call db.index.fulltext.drop("nameAndDescription")
唯一性约束
作用
创建唯一性约束
CREATE CONSTRAINT ON (变量:
) ASSERT 变量. IS UNIQUE
具体实例:
CREATE CONSTRAINT ON (person:Person) ASSERT person.name IS UNIQUE
删除唯一性约束
DROP CONSTRAINT ON (cc:Person) ASSERT cc.name IS UNIQUE
3.5.2 属性存在约束 (企业版中可用)
CREATE CONSTRAINT ON (p:Person) ASSERT exists(p.name)
查看约束
call db.constraints
:schema
在对Neo4j数据进行备份、还原、迁移的操作时,首先要关闭neo4j
./bin/neo4j stop
数据备份到文件
./bin/neo4j-admin dump --database=graph.db --to=/root/qyn.dump
还原、迁移之前 ,关闭neo4j服务。操作同上
./bin/neo4j-admin load --from=/root/qyn.dump --database=graph.db --force
重启服务
./bin/neo4j start
注意,运行数据备份可能会警告
WARNING: Max 1024 open fifiles allowed, minimum of 40000 recommended. See the Neo4j
manual
1.编辑这个文件
vi /etc/security/limits.conf
在文件最后加入下面这段 修改最大打开文件限制
* soft nofile 65535
* hard nofile 65535
2.重启服务器
再次执行上面的步骤 警告就没有了
增加服务器内存 和 调整neo4j配置文件
# java heap 初始值
dbms.memory.heap.initial_size=1g
# java heap 最大值,一般不要超过可用物理内存的80%
dbms.memory.heap.max_size=16g
# pagecache大小,官方建议设为:(总内存-dbms.memory.heap.max_size)/2,
dbms.memory.pagecache.size=2g
neo4j刚启动数据是冷的需要预热
MATCH (n)
OPTIONAL MATCH (n)-[r]->()
RETURN count(n.name) + count(r);
查看执行计划进行索引优化
Cypher查询计划程序将每个查询转换为执行计划。 执行计划告诉Neo4j在执行查询时要执行哪些操作。
对执行计划的生成,Neo4j使用的都是基于成本的优化器(Cost Based Optimizer,CBO),用于制订精确的执行过程。可以采用如下两种不同的方式了解其内部的工作机制:
EXPLAIN:是解释机制,加入该关键字的Cypher语句可以预览执行的过程但并不实际执行,所以也不会产生任何结果。
PROFILE:则是画像机制,查询中使用该关键字,不仅能够看到执行计划的详细内容,也可以看到查询的执行结果。
关注指标:
estimated rows: 需要被扫描行数的预估值
dbhits: 实际运行结果的命中绩效
两个值都是越小越好
使用索引和不使用索引对比
profile MATCH (p { name : '小张' }) RETURN p
在之前加上profile来进行查询,可以查看查询计划
1.导入jar包
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.6.9
com.zql
spring-boot-neo4j-demo
0.0.1-SNAPSHOT
spring-boot-neo4j-demo
Demo project for Spring Boot
11
org.springframework.boot
spring-boot-starter-data-neo4j
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
2.配置文件 application.yml
spring:
data:
neo4j:
username: neo4j
password: neo4j
uri: bolt://localhost:7687
3.建立实体类
@Data
@ToString
public class Person {
@Id
@GeneratedValue
private Long id;
@Property("cid")
private int pid;
@Property
private String name;
private String character;
private double money;
private int gender;
private int age;
private String description;
}
4.数据持久化类
@Repository
public interface PersonRepository extends Neo4jRepository {
@Query("MATCH (p:Person) where p.money > $money return p")
List personList(@Param("money")Double money);
@Query("MATCH p=shortestPath((person:Person {name:{0}})-[*1..4]- (person2:Person {name:{1}}) ) RETURN p")
List shortestPath(String startName,String endName);
}
5.编写服务类
@Service
public class Neo4jPersonService {
@Autowired
private PersonRepository personRepository;
public List personList(Double money){
return personRepository.personList(money);
}
public List personAll(){
return personRepository.findAll();
}
public Person save(Person person){
return personRepository.save(person);
}
public List shortestPath(String startName, String endName){
return personRepository.shortestPath(startName,endName);
}
}
6.编写测试类
@SpringBootTest
class SpringBootNeo4jDemoApplicationTests {
@Autowired
private Neo4jPersonService neo4jPersonService;
/**
* 添加节点
*/
@Test
void save() {
Person person = new Person();
person.setAge(22);
person.setName("小张");
person.setGender(1);
person.setMoney(10000);
person.setGender(1);
person.setDescription("描述");
person.setCharacter("哈哈哈");
person.setPid(2);
Person person1 = neo4jPersonService.save(person);
System.out.println(person1);
}
/**
* 查询所有节点
*/
@Test
void selectAll() {
List personList = neo4jPersonService.personAll();
System.out.println(personList);
}
/**
* 根据条件查询节点
*/
@Test
void condition() {
List personList = neo4jPersonService.personList(new Double(1000));
System.out.println(personList);
}
/**
* 最短路径
*/
@Test
void shortestPath() {
List personList = neo4jPersonService.shortestPath("小张", "王武");
System.out.println(personList);
}
}