neo4j

引入neo4j

案例

假设郭富城希望找向华强拍电影,应该怎么找到他。

neo4j数据库和mysql基础语法 neo4j mysql_neo4j数据库和mysql基础语法

使用mysql数据库
创建数据库和表
-- 创建数据库
CREATE DATABASE IF NOT EXISTS neo4j
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_0900_ai_ci;

-- 创建明星表
CREATE TABLE star (
	id INT ( 11 ) NOT NULL AUTO_INCREMENT,
	homepage VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL,
	NAME VARCHAR ( 255 ) COLLATE utf8_bin NOT NULL,
	sex VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL COMMENT '性別',
	occupation VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL COMMENT '职业',
	PRIMARY KEY ( id ),
	UNIQUE KEY NAME ( NAME ) USING BTREE,
    KEY homepage ( homepage ) USING BTREE 
) ENGINE = INNODB AUTO_INCREMENT = 1792 DEFAULT CHARSET = utf8 COLLATE = utf8_bin;

-- 插入数据
INSERT INTO star ( NAME, sex, occupation )VALUES( '郭富城', '男', '演员' );
INSERT INTO star ( NAME, sex, occupation )VALUES( '朱茵', '女', '演员' );
INSERT INTO star ( NAME, sex, occupation )VALUES( '向华强', '男', '演员' );
INSERT INTO star ( NAME, sex, occupation )VALUES( '周星驰', '男', '演员' );
INSERT INTO star ( NAME, sex, occupation )VALUES( '张敏', '女', '演员' );
INSERT INTO star ( NAME, sex, occupation )VALUES( '舒淇', '女', '演员' );
	
-- 创建明星关系表
CREATE TABLE star_relation (
	id INT ( 11 ) NOT NULL AUTO_INCREMENT,
	from_name VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL,
	relation VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL,
	to_name VARCHAR ( 255 ) COLLATE utf8_bin DEFAULT NULL,
	PRIMARY KEY ( id ),
	UNIQUE KEY from_name ( from_name, relation, to_name ) USING BTREE 
) ENGINE INNODB AUTO_INCREMENT = 6792 DEFAULT CHARSET = utf8 COLLATE utf8_bin;

-- 插入数据
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '郭富城', '好友', '朱茵' );
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '朱茵', '旧爱', '周星驰' );
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '周星驰', '爱人', '张敏' );
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '张敏', '老板', '向华强' );
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '郭富城', '好友', '舒淇' );
INSERT INTO star_relation ( from_name, relation, to_name )VALUES( '舒淇', '老板', '周星驰' );
查询郭富城和向华强的关系

常见错误

SELECT
	* 
FROM
	star_relation a
	LEFT JOIN star_relation b ON a.from_name = b.to_name 
WHERE
	a.from_name = '郭富城' 
	AND b.to_name = '向华强';

运行结果

neo4j数据库和mysql基础语法 neo4j mysql_数据库_02

正确查询

SELECT DISTINCT
	a.from_name,
	b.from_name,
	c.from_name,
	d.from_name,
	e.from_name 
FROM
	star_relation a
	LEFT JOIN star_relation b ON a.from_name = b.to_name
	LEFT JOIN star_relation c ON b.from_name = c.to_name
	LEFT JOIN star_relation d ON c.from_name = d.to_name
	LEFT JOIN star_relation e ON d.from_name = e.to_name 
WHERE
	a.from_name = '郭富城' 
	AND e.from_name = '向华强';

运行结果

neo4j数据库和mysql基础语法 neo4j mysql_java_03

使用neo4j数据库
创建节点和关系
-- 创建Star节点
create (:Star{name:"郭富城",sex:"男",occupation:"演员"});
create (:Star{name:"舒淇",sex:"女",occupation:"演员"}); 
create (:Star{name:"朱茵",sex:"女",occupation:"演员"});
create (:Star{name:"周星驰",sex:"男",occupation:"演员"});
create (:Star{name:"张敏",sex:"女",occupation:"演员"});
create (:Star{name:"向华强",sex:"男",occupation:"企业家"});

-- 创建Star_Relation关系
match (a:Star{name:"郭富城"}) match(b:Star{name:"舒淇"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"郭富城"}) match(b:Star{name:"朱茵"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"舒淇"}) match(b:Star{name:"郭富城"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"舒淇"}) match(b:Star{name:"周星驰"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"朱茵"}) match(b:Star{name:"郭富城"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"朱茵"}) match(b:Star{name:"周星驰"}) create (a) - [r:Star_Relation{relation:'旧爱'}] -> (b) return r;
match (a:Star{name:"周星驰"}) match(b:Star{name:"朱茵"}) create (a) - [r:Star_Relation{relation:'旧爱'}] -> (b) return r;
match (a:Star{name:"周星驰"}) match(b:Star{name:"张敏"}) create (a) - [r:Star_Relation{relation:'同事'}] -> (b) return r;
match (a:Star{name:"周星驰"}) match(b:Star{name:"舒淇"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"张敏"}) match(b:Star{name:"周星驰"}) create (a) - [r:Star_Relation{relation:'同事'}] -> (b) return r;
match (a:Star{name:"张敏"}) match(b:Star{name:"向华强"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;
match (a:Star{name:"向华强"}) match(b:Star{name:"张敏"}) create (a) - [r:Star_Relation{relation:'好友'}] -> (b) return r;

-- 删除所有star节点和关系
match (n:Star{}) - [r] - () delete r,n;
查询郭富城和向华强的关系
match p=(a:Star{name:"郭富城"}) - [*] -> (b:Star{name:"向华强"}) return p
运行结果

neo4j数据库和mysql基础语法 neo4j mysql_Pig_04

案例总结

mySql虽然称作关系型数据库,但在处理数据之间的较多关系的时候却显的力不从心。原因在于关系型数据库是以通过外键去匹配主表中的主键来进行搜索,这种匹配操作是“计算密集型"的随着表中记录增加将会消耗更多的系统资源。所以关系型数据库无法应对像facebook、脉脉好友推荐这类业务的存储实现。

提问

facebook、脉脉、人人网这类社交推荐应用如何实现?

neo4j数据库和mysql基础语法 neo4j mysql_java_05

图数据库(Graph Database)

什么是图数据库

图数据库(graph database)是基于图论实现的一种新型noSql数据库,其数据库存储结构和数据的查询方式都是以图论为基础的。图论中图的基本元素为节点和边,在图数据库中对应的就是节点和关系。它的优点是快速解决复杂的关系问题。

数据结构:
在一个图中主要包含两种数据类型:Nodes(节点)和Relationships(关系)。他们各自内部又包含key-value形式的属性,然后节点之间通过关系相连,形成了关系型的网状结构。

关于图论?

图论[Graph Theory]是数学的一一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。

neo4j数据库和mysql基础语法 neo4j mysql_Pig_06


图型数据库应用场景

1.第一方银行欺炸

2.保险欺诈

3.电子商务欺诈

4.工商企业图普

5.社交网络

neo4j图数据库中基本元素与概念

节点(node)

表示一个实体记录、就像关系数据库当中一条记录。 一个节点包含多个属性和标签。

关系(relationship)

关系用于将节点关联起来构成图,关系也称为图论的边(Edge)。

属性(property)

节点和关系都可以有多个属性。属性是由键值对组成的,就像JAVA当中哈希。

标签(Label)

标签指示一组拥有相同属性的节点,但不强制要求相同,一个节点可以有多个标签。

路径(path)

图中任意两个节点都存在由关系组成的路径,路径有长短之分。

Cypher查询语言

概念

Cypher是一种声明式图数据库查询语言,类似关系数据库中当中SQL。Cypher设计借鉴了基它回如SQL、Python语言惯用做法,初学者非常容易上手。

  • MATCH:匹配图模式
  • WHERE:过滤条件
  • RETURN:定义返回的结果
基本语法
  • 增(CREATE)
  • 删(DELETE)
  • 改(SET)
  • 查(MATCH)
示例练习

小猪佩奇家庭族谱示例

neo4j数据库和mysql基础语法 neo4j mysql_数据库_07

快速入门

-- 创建一个猪爷爷节点
create (:Pig{name:"猪爷爷",age:15});  
-- 创建一个猪奶奶节点
create (:Pig{name:"猪奶奶",age:13});  
-- 创建猪爷爷和猪奶奶是夫妻关系
match (a:Pig{name:"猪爷爷"}) match (b:Pig{name:"猪奶奶"}) create (a) - [r:夫妻] -> (b) return r;

简便方式

-- 创建一个猪爸爸和一个猪妈妈节点,并建立他们为夫妻关系,婚龄5年
create (:Pig{name:"猪爸爸",age:12})-[:夫妻{age:5}]->(:Pig{name:"猪妈妈",age:9});  
-- 创建一个佩奇和一个乔治节点,并建立他们为姐弟关系
create (:Pig{name:"佩奇",age:2})-[:姐弟]->(:Pig{name:"乔治",age:1});

建立关系

-- 创建猪爷爷和猪爸爸是父子关系
match (a:Pig{name:"猪爷爷"}) match (b:Pig{name:"猪爸爸"}) create (a) - [r:父子] -> (b) return r;  
-- 创建猪爸爸和佩奇是父女关系
match (a:Pig{name:"猪爸爸"}) match (b:Pig{name:"佩奇"}) create (a) - [r:父女] -> (b) return r;  
-- 创建猪爷爷和佩奇是孙女关系
match (a:Pig{name:"猪爷爷"}) match (b:Pig{name:"佩奇"}) create (a) - [r:孙女] -> (b) return r;  
-- 创建猪奶奶和佩奇是孙女关系
match (a:Pig{name:"猪奶奶"}) match (b:Pig{name:"佩奇"}) create (a) - [r:孙女] -> (b) return r;  
-- 创建猪奶奶和猪爸爸是母女关系
match (a:Pig{name:"猪奶奶"}) match (b:Pig{name:"猪爸爸"}) create (a) - [r:母女] -> (b) return r;
-- 查询pig节点
MATCH (n:Pig) RETURN n LIMIT 25

neo4j数据库和mysql基础语法 neo4j mysql_Pig_08

-- 将猪妈妈的年龄改为8
match (n:Pig{name:"猪妈妈"}) set n.age=8;
-- 创建一个多节点猪祖父和一个猪祖奶节点
create (:Die:Pig{name:"猪祖父",age:30}),(:Pig{name:"猪祖奶",age:28});
-- 删除die标签下的所有节点
MATCH (n:Die) delete n;