1、入门介绍
一、案例总结
mysql虽然称作为关系型数据库,但是在处理数据之间的较多关系的时候却显得力不从心,原因在于关系型数据库是以通过外键的匹配主表钟的之间来进行搜索,这种匹配操作是“计算密集型”的随着表中的记录增加将会消耗更多的系统资源,所以关系型数据库无法应对像facebook、脉脉好友推荐、运维服务器-集群-机房-机柜-物理机-云主机等等的存储实现
二、什么是图形数据库
mysql图形数据库是基于图论实现的一种新型nosql的数据库,其数据库存储结构和数据查询方式都是以图论为基础的,图论钟图的基本元素为节点和边,在图数据库中对应的就是节点和关系
a、节点
b、关系
图论:是一个数学的分支,他以图为研究对象,图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某种事务之间的某种特定关系,用点代表事物,用连接两点的线来表示两个事物间具有这种关系
三、图形数据库应用场景
1、资源池~~~服务器之间的关联关系图谱
2、天眼查的股定到公司的架构关系图谱
3、工商企业图谱
4、社交网络
二、neo4j安装以及入门实例
#1、安装检测jdk环境1.8
#2、下载程序包 http://neo4j.com/download/other-releases/#releases
#下载社区版
wget http://neo4j.com/artifact.php?name=neo4j-community-3.2.10-unix.tar.gz
#解压
tar -zxvf neo4j-community-3.2.10-unix.tar.gz
#修改配置文件
vim conf/neo4j.conf
#放开访问权限
dbms.connectors.default.listen_address=0.0.0.0
#3、启动
#启动
./bin/neo4j start
#停止
./bin/neo4j stop
#4、访问WEB管理页
http://ip:7474/browser/
三、neo4j图形数据库中基本元素及概念
1、节点(node)
标识一个实体记录,就像关系数据当中的一条记录,一个节点包含多个属性和标签
2、关系(relationship)
关系用于将节点关联起来构成图,关系也成为图论的边(Edge)
3、属性(property)
节点和关系都可以有多个属性,属性是由键值对组成的,就像JAVA当中的哈希
4、标签(Label)
标签指示一组拥有相同属性的节点, 但不强制要求相同,一个节点可以有多个标签
5、路径(path)
图中任意两个节点都存在由关系组成的路径,路径有长短之分
四、Cypher查询语言
1、概念:Cypher是一种声明式图数据库查询语言,类似关系数据库当中sql,Cypher设计借鉴了其它如SQL、Python语言管用做法,初学者容易上手
MATCH:匹配图模式
WHERE:过滤条件
RETURN:定义返回的结果
2、基本语法:
增加(CREATE)
删除(DELETE)
修改(SET)
查询(MATCH)
函数
witch
聚合
3、小猪佩奇示例
create(:pig{name:"猪爷爷",age:15});
create(:pig{name:"猪奶奶",age:13});
match(a:pig(name:"猪爷爷",age:15)) match(b:pig{name:"猪奶奶",age:13}) create (a)-[r:fuqi]
->(b) return r;
#也可以一次性创建节点和关系(还可以给关系加属性)
create(:pig{name:"猪爸爸",age:10})-[:fuqi{age:5}]->(:pig{name:"猪妈妈",age:8});
create(:pig{name:"佩奇",age:5})-[:jiedi]->(:pig{name:"乔治",age:3});
match(a:pig(name:"猪爸爸")) match(b:pig{name:"猪爷爷"}) create (b)-[r:fuzi]
->(a) return r;
match(a:pig(name:"猪爸爸")) match(b:pig{name:"猪爷爷"}) create (b)-[r:fuzi]
->(a) return r;
match(a:pig(name:"猪爷爷")) match(b:pig{name:"佩奇"}) create (a)-[r:sunnv]
->(b) return r;
#还可以创建多标签
create(:die:pig{name:"猪祖父",age:15});
#修改属性
match(a:pig(name:"猪爷爷",age:15)) set a.age=5
#删除节点 删除die标签下的所有节点
match (n:die) delete n;
4、获取两个节点之间最短节点 5指定了最大路径
match p=shortestpath((a:Star(name:"a1")-[*..5]->(b:Star(name:"a2")))) return p
match p=allshortestpath((a:Star(name:"a1")-[*..5]->(b:Star(name:"a2")))) return p
5、查询跟王菲相关的所有人
return (:Star(name:"王菲"))-->() limit 50;
五、neo4j程序开发
1、java嵌入式开发模式
neo4j基于java语言开发的,在第一版发布之初是专门针对java领域等等,所以它能够与java开发天然结合,java程序可以直接集成在neo4j库到应用当中
2、restful接口调用
http://192.168.0.147:7474/db/data/ #返回数据库的相关信息
3、java调用
#yml文件配置
spring:
data:
neo4j:
uri: http://localhost:7474
username: neo4j
password: 123456
<!-- 添加依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
@NodeEntity,标记该类为节点,节点名称为 BaseNode
@Getter
@Setter
@ToString
@NodeEntity
public class BaseNode {
/**
* neo4j 生成的id
*/
@Id
@GeneratedValue
private Long id;
/**
* 属性,name
*/
private String name;
/**
*
*/
private Integer age;
/**
* 关系,定义为友谊
*/
@Relationship(type = "BASERELATIONSHIP_RELATION")
private List<BaseRelationship> BaseRelationshipList;
}
@RelationshipEntity,标记其为关系,关系名为 BASERELATIONSHIP_RELATION,在里面定义StartNode和EndNode
@Getter
@Setter
@Component
@RelationshipEntity(type = "BASERELATIONSHIP_RELATION")
public class BaseRelationship{
@Id
@GeneratedValue
private Long id;
@StartNode
private BaseNode from;
@EndNode
private BaseNode to;
//Node节点操作
@Repository
public interface BaseNodeRepository extends Neo4jRepository<BaseNode, String> {
//可以使用spring data风格使用默认的方法名查询
List<BaseNode> findByCode(String code);
List<BaseNode> findById(String Id);
//根据年龄查找所有的节点
@Query(value="MATCH (n:BaseNode) where n.age={age} return n")
List<BaseNode> getlistByAge(int age);
|
//关联关系操作
@Repository
public interface BaseRelationshipRepository extends Neo4jRepository<BaseRelationship, String> {
//根据节点的名字查找对应的关联关系
@Query("MATCH (a:BaseNode)-[r:Ref]->(b:BaseNode) WHERE a.name={startName} and b.name={endName} RETURN a,p,b")
List<BaseRelationship> findStartToEndRelationship(String startName, String endName);
}
Neo4jServiceImpl中定义添加关系和删除关系,都需要保存from端的节点关系即可
删除节点时使用了find和save方法,需要添加@Transactional注解
@Service("neo4jServiceImpl")
public class Neo4jServiceImpl implements Neo4jService {
@Autowired
private BaseNodeRepository baseNodeRepository;
@Override
public void saveBaseRelationship(String fromName, String toName) {
BaseNode from = baseNodeRepository.findByName(fromName);
BaseNode to = baseNodeRepository.findByName(toName);
BaseRelationship baseRelationship = new BaseRelationship();
baseRelationship.setFrom(from);
baseRelationship.setTo(to);
//只需要在from节点保存关系即可
from.addRelation(baseRelationship);
baseNodeRepository.save(from);
}
//删除节点时,使用find,save 需要@Transactional注解
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteBaseRelationship(String fromName, String toName) {
BaseNode fromBaseNode = baseNodeRepository.findByName(fromName);
List<BaseRelationship> baseRelationshipList = fromStudentNode.findStartToEndRelationship();
for (Iterator<BaseRelationship> iterator = baseRelationshipList.iterator(); iterator.hasNext();) {
BaseRelationship relation = iterator.next();
BaseNode fromNode = relation.getFrom();
BaseNode toNode = relation.getTo();
String fromNodeName = fromNode.getName();
String toNodeName = toNode.getName();
//判断 fromName 和 toName 需要删除的关系是否相等
if(fromNodeName.equals(fromName) && toNodeName.equals(toName)){
iterator.remove();
}
}
//只需要在from节点保存关系即可
baseNodeRepository.save(fromStudentNode);
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class Neo4jTest {
@Autowired
private BaseNodeRepository baseNodeRepository;
@Autowired
private Neo4jService neo4jService;
/**
* 保存单个节点
*/
@Test
public void saveBaseNode(){
BaseNode BaseNode = new BaseNode();
BaseNode.setName("张0");
baseNodeRepository.save(BaseNode);
}
/**
* 通过name查询学生节点
*/
@Test
public void findBaseNodeByName(){
BaseNode BaseNode = baseNodeRepository.findByName("张0");
System.out.println("");
}
/**
* 保存批量节点
*/
@Test
public void saveAllBaseNode(){
List<BaseNode> BaseNodeList = new ArrayList<>();
BaseNode BaseNode;
for(int i = 1; i <= 10; i++){
BaseNode = new BaseNode();
BaseNode.setName("张" + i);
BaseNodeList.add(BaseNode);
}
baseNodeRepository.saveAll(BaseNodeList);
}
/**
* 查询全部
*/
@Test
public void findAll(){
//iterable to list
List<BaseNode> BaseNodeList = Lists.newArrayList(baseNodeRepository.findAll());
System.out.println("");
}
/**
* 分页查询
*/
@Test
public void pageFindAll(){
Pageable pageable = PageRequest.of(0,2);
Page<BaseNode> BaseNodePage = baseNodeRepository.findAll(pageable);
System.out.println("");
}
/**
* 保存如下友谊关系
*/
@Test
public void saveBaseRelationship(){
neo4jService.saveBaseRelationship("张1","张2");
}
/**
* 删除 1 -> 3 友谊关系
*/
@Test
public void deleteFriendship(){
neo4jService.deleteFriendship("张1","张3");
}
}