上一篇:Neo4j:简介与初体验
![9bd2be82b7f675a9388ac45a05e866b3.png](https://img.php1.cn/3cd4a/1eebe/cd5/c72d78d7317a9e8e.webp)
Neo4j,作为一个存储图的数据库,与其他关系型、非关系型数据库一样,提供了很简单易用的增删改查语句。
CQL,Cypher查询语言。像Oracle数据库具有查询语言SQL,Neo4j用CQL作为查询语言。
作为CQL,它有如下特点:
1、它是Neo4j图形数据库查询语言
2、它是一声明性模式匹配语言(个人使用起来的感觉,像lambd表达式)
3、语法非常简单(个人感觉,语法能表现出很清晰的图结构)
我们启动Neo4j并登录Neo4j提供的UI界面(可以参考这个文章启动和登录Neo4j:简介与初体验 )。
本节,教大家如何使用最基本的CQL语言,完成最基本的增删改查。Neo4j常用的命令如下:
命令 | 含义 | 对比MySQL |
create | 创建节点 | insert插入数据 |
match | 查询 | select |
return | 返回数据 | |
where | 条件查询 | where |
delete | 删除关系、节点 | delete |
order by | 排序 | order by |
set | 修改 | update |
另外,由于Neo4j是Java开发的,所以支持Java的8大基本数据类型,再加一个String类型
数据类型 | 说明 |
boolean | 布尔:true or false |
byte | 用于表示8位整数 |
short | 用于表示16位整数 |
int | 用于表示32位整数 |
long | 用于表示64位整数 |
float | 用于32位浮点数 |
double | 用于64位浮点数 |
char | 用于表示16位字符串 |
String | 用于表示字符串 |
Neo4j提供的Web UI界面使用起来很简单,界面如下:
![0ad4879a08b8c00a66c75a88b2abbd4f.png](https://img.php1.cn/3cd4a/189d8/978/7dbdf0f38ad53545.jpeg)
HelloWorld走起来~~
为了让大家尽快熟悉使用语法,我在这里分别用CQL和SQL对照着写。
创建节点:
基本语法:create (node:Label {属性1:属性值1,属性2:属性值2})
CQL:
create (u0:User {name:"张三",age:18}) create (u1:User {name:"李四",age:19}) return u0,u1
SQL:
create table user(name varchar(20),age int);insert into user (name,age) values("张三",18);
说明:和关系型数据库不同的是,Neo4j写入数据时,不需要先创建schema。上述CQL的含义是:在Label名是User的标签下创建两个节点,u0和u1,以及他们的属性name和age,并返回。
查询:
CQL:
match (u:User) return u;match (u:User) where u.age=18 return u;match (u:User {name:"张三"}) return u;match (u:User) where u.age = 18 return u.name;
SQL:
select * from User;select * from User where age=18;select * from User where name='张三';select name from user where age=18;
说明:这是最简单的条件查询,使用match、where和return关键字。从标签名为User的Label(从表名为User的表)中查数据。
创建关系:
和关系型数据库不同的是,Neo4j的node和node间是有关系的,我们可以把它理解成MySQL中的外键,但是还是有区别的哦。
match (u0:User {name:"张三"}),(u1:User {name:"李四"}) create (u0)-[r:friend]->(u1) return u0,r,u1
![c117ec04a0eaaf0c17eb8e70b7a7f0a3.png](https://img.php1.cn/3cd4a/1eebe/cd5/b428d8f746fb8d47.webp)
创建节点u0到节点u1的关系friend。如果多次执行上面的语句,两个节点可以创建多个关系
![52d5cc45ae18850ff8cf01608d1f2619.png](https://img.php1.cn/3cd4a/1eebe/cd5/d942b7ec373849c3.webp)
当然也可以创建反向关系(注意两条CQL语句关系箭头的方向不同)。
match (u0:User {name:"张三"}),(u1:User {name:"李四"}) create (u0)-[r:friend]->(u1)return u0,r,u1match (u0:User {name:"张三"}),(u1:User {name:"李四"}) create (u0)<-[r:friend]-(u1)return u0,r,u1
![b239716dac3e78a7b4918b6effff4c88.png](https://img.php1.cn/3cd4a/1eebe/cd5/8343fdbffb0056b5.webp)
说明&#xff1a;有没有发现&#xff0c;CQL的语法和图的数据结构很类似&#xff0c;基本语法是&#xff1a;
match (node1),(node2) create node1-[r:relation]->node2
可以理解为&#xff0c;查出两个节点node1和node2&#xff0c;创建从node1到node2的关系r。
删除&#xff1a;
基本语法&#xff1a;
match (u:User) delete u;
通过match查询出结果集&#xff0c;然后delete u。
需要注意的是&#xff1a;
Neo4j节点与节点的关系&#xff0c;和MySQL两张表中数据的外键很相似&#xff0c;在MySQL中&#xff0c;如果两张表之间有外键关联&#xff0c;我们不能直接删除主键表的数据&#xff0c;需要先删除外键表的数据后才能删除主键表。所以Neo4j中&#xff0c;我们不能直接删除两个有relationship的节点&#xff0c;需要先删除他们的关系&#xff0c;再删除节点。如果我们直接删除有关系的两个节点&#xff0c;将会报如下的错&#xff1a;
![3824415af96d7f08dca074b4d6669e21.png](https://img.php1.cn/3cd4a/1eebe/cd5/d84f9786330d9e41.png)
所以我们需要先删除两个节点之间的关系。
match (u:User {name:"张三"})-[r:friend]->(u1:User {name:"李四"}) delete r
![bd12a39879a34995bec8572fad8f2dd3.png](https://img.php1.cn/3cd4a/1eebe/cd5/0d80e8a685a9a87b.png)
和上图对比&#xff0c;张三和李四有一个双向的关系&#xff0c;删除张三到李四的关系&#xff0c;只剩下李四到张三的关系&#xff0c;我们继续删除李四到张三的关系(注意箭头的指向)&#xff1a;
match (u:User {name:"张三"})<-[r:friend]-(u1:User {name:"李四"}) delete r
![de7362c172098f741bf6f573560ec9f9.png](https://img.php1.cn/3cd4a/1eebe/cd5/7494af3c1cda418d.webp)
最后&#xff0c;我们才能删除节点
match (u:User) where u.name&#61;&#39;张三&#39; delete u;match (u:User) delete u;
和下面的SQL含义相同
delete from User where name&#61;&#39;张三&#39;delete from User;
排序&#xff1a;
match (u:User) return u.name,u.age order by u.age desc;match (u:User) return u.name,u.age order by u.age asc;
和下面的SQL含义相同&#xff1a;
select name,age from User order by age desc;select name,age from User order by age asc;
Set修改&#xff1a;
match (u:User {name:"张三"}) set u.name &#61; &#39;张三丰&#39; return u;match (u:User {name:"张三丰"}) set u.sex &#61; &#39;男&#39; return u.name,u.age,u.sex;
和下面的SQL含义相同&#xff1a;
update User set name&#61;&#39;张三丰&#39; where name&#61;&#39;张三&#39;;
最后返回的结果是&#xff1a;
![88f9072e1ee4d05f0773399a2466cbe5.png](https://img.php1.cn/3cd4a/1eebe/cd5/8170a21e8dddfd22.webp)
上面所列举的增删改查语句&#xff0c;是比较基本的。并且语法不止一种&#xff0c;CQL的语法比较随意。当然&#xff0c;还有其他的操作&#xff0c;比如remove&#xff0c;union等操作&#xff0c;在此处就不一一举例&#xff0c;大家可以查阅相关资料。
实战
我们以苏轼一大家子举例&#xff0c;首先创建苏轼一大家子节点&#xff1a;
create(suxun:Person_{name:"苏洵",age:80,sex:"男"})create(sushi:Person_{name:"苏轼",age:53,sex:"男"})create(suzhe:Person_{name:"苏辙",age:51,sex:"男"})create(suxiaomei:Person_{name:"苏小妹",age:45,sex:"女"})create(susun:Person_{name:"苏孙",age:29,sex:"男"})create(suxiaosun:Person_{name:"苏重孙",age:6,sex:"女"})
![dbdf3abadf00788ffef8886d9e1309c0.png](https://img.php1.cn/3cd4a/1eebe/cd5/d67981797265d9c7.webp)
根据上述排列&#xff0c;我们知道&#xff0c;苏洵是长辈&#xff0c;苏轼苏辙苏小妹属于同一辈份&#xff0c;苏孙是苏轼的儿子&#xff0c;苏重孙是苏轼的孙子。。。
然后我们创建关系&#xff1a;
match(p1:Person_),(p2:Person_)where p1.name&#61;"苏洵" and p2.name &#61; "苏轼"create (p1) -[parent:Parent{relation:"父亲"}]-> (p2); match(p1:Person_),(p2:Person_)where p1.name&#61;"苏洵" and p2.name &#61; "苏辙"create (p1) -[parent:Parent{relation:"父亲"}] -> (p2); match(p1:Person_),(p2:Person_)where p1.name&#61;"苏洵" and p2.name &#61; "苏小妹"create (p1) -[parent:Parent{relation:"父亲"}] -> (p2); match(p1:Person_),(p2:Person_)where p1.name&#61;"苏轼" and p2.name &#61; "苏孙"create (p1) -[parent:Parent{relation:"父亲"}] -> (p2); match(p1:Person_{name:"苏孙"}),(p2:Person_{name:"苏重孙"})create (p1) -[parent:Parent{relation:"父亲"}] -> (p2);
![d6d293cef4b4461d30ae9ed825efe173.png](https://img.php1.cn/3cd4a/1e618/c5a/d5d40da532c3a782.png)
我们根据条件写出CQL语句&#xff1a;
1、筛选出子孙绵延四代的树干&#xff1a;
match(a)-[r1:Parent]->(b)-[r2:Parent]->(c)-[r3:Parent]->(d) return a, b, c, d
![2c425aa9f92cf7c432779088b70d44b8.png](https://img.php1.cn/3cd4a/1eebe/cd5/3e641eb5f5c8cd90.webp)
2、筛选出存在三代子孙的树干&#xff1a;
match(a)-[r1:Parent]->(b)-[r2:Parent]->(c) return a, b, c
![2c425aa9f92cf7c432779088b70d44b8.png](https://img.php1.cn/3cd4a/1eebe/cd5/3e641eb5f5c8cd90.webp)
看起来是一根树干&#xff0c;其实有两组数据
![bc8e29550ee561982d02fbfbb6f34f18.png](https://img.php1.cn/3cd4a/1eebe/cd5/43a754c811e7ec5c.webp)
3、筛选出以某个节点为顶点的三代子孙树干&#xff1a;
match(a:Person_{name:"苏洵"})-[r1:Parent]->(b)-[r2:Parent]->(c) return a, b, c
![c68106644a3c1ef7a732c0334769ac20.png](https://img.php1.cn/3cd4a/1eebe/cd5/0d80e8a685a9a87b.png)
好了&#xff0c;本次的分享就到这里&#xff0c;谢谢大家。