图数据库概念
以“图”这种数据结构存储和查询数据,neo4j为其典型代表。
对于图数据库来说,数据量越大,越复杂的关联查询,越有利于体现其优势——查询性能优势明显。
数据模型
- 实体(Entity)
- 节点(Node)
- 关系(Relationship)
- 边/路径(Path)
- 记号(Token)
- 标签(Label)
- 关系类型(Relationship Type)
- 属性键(Property Key)
- 属性(Property)
实体
- 每一个Neo4j图数据库中的实体都拥有一个用于区分实体与实体之间是否相等的唯一标识;
- 每一个Neo4j图数据中的实体都可以分配一组属性key以及对应的属值(value),同一个实体中的属性key都是唯一的,并且不能为空的以及空字符串;
节点
- Neo4j图数据库中节点都是建立在实体的之上的一种抽象,拥有属性和属性值;
- 一个节点可以被分配一组唯一的标签;
- 一个节点可以有0个或者多个向外或向内(边/路径的指向,分为向外和向内两种)的关系;
关系
- 关系是一个建立两个节点之间关系,由源节点指向目标节点的实体;
- 一个向外的关系,是源节点由自身关联目标节点的一种关系;
- 一个向内的关系,是源端节点自身被关联的一种关系;
- 每一个关系都必须分配一个且唯一的关系类型;
- 关系也是实体,可以拥有属性和属性值;
边/路径
- 边/路径表示一个属性图的关系,由一系列交替的节点和关系组成;
- 一个边/路径总是由开始于节点,终止于节点;
- 最小的边/路径只包含单个节点,这类型的边叫做空边/空路径;
- 边/路径有一个长度(深度),它是大于或等于0的整数,等于路径中的关系数;
记号
记号是一个非空的Unicode字符串。
- 标签:标签是一个分配给节点的一个唯一的记号。
- 关系类型:关系类型是被分配给关系的一个唯一的记号
- 属性key:属性key是一个存在于实体中的唯一属性字段,类似于Json对象中的key。
属性:
属性由一对属性key和属性值组成,类似于Json字符串中的key:value。
CQL
像Oracle数据库具有查询语言SQL,Neo4j具有CQL作为查询语言。
创建节点(create)
在创建节点的时候,数据库会自动为节点分配一个id,id是节点的唯一标识,一个id对应一个节点。
⭐️如果连续创建同样的节点,会是两个id,所以一般在增加时注意判断节点是否存在。
创建没有属性的节点
CREATE (<node-name>:<label-name>)
//创建标签为学生的一个节点
create (n:学生)
创建多个属性的节点
CREATE (
<node-name>:<label-name>
{
<Property1-name>:<Property1-Value>
........
<Propertyn-name>:<Propertyn-Value>
}
)
//n——节点名 学生——节点的标签名 姓名、年龄、性别——属性名
//标签名和属性名不用引号修饰,但是属性值如果是字符串需要加引号
create (n:学生 {姓名:'王二',年龄:18,性别:'男'})
创建多标签的节点
CREATE (<node-name>:<label-name1>:<label-name2>.....:<label-namen>)
//创建一个即是学生又是父亲的两个标签的节点
CREATE (n:学生:父亲)
//为已经存在的“王二”节点添加“父亲”标签
MATCH (学生 {姓名:"王二"}) set 学生:父亲
创建关系(create)
创建新关系
CREATE
(<node1-name>:<node1-label-name>)-
[<relationship-label-name>:<relationship-name>]->
(<node1-name>:<node2-label-name>)
RETURN <relationship-label-name>//可以不加return,加了return可以查看相应的关系
//创建了LIKES关系类型,学生->老师, 新节点+新关系+无属性关系
//如果已经存在LIKES该关系类型已经存在,不会产生新的关系,但是会新建两个空节点(学生节点和老师节点)
CREATE (n:学生)-[relationship:LIKES]->(m:老师)
RETURN LIKES
创建有属性的关系
CREATE
(<node1-name>:<node1-label-name>{<define-properties-list>})-
[<relationship-name>:<relationship-label-name>{<define-properties-list>}]
->(<node1-name>:<node1-label-name>{<define-properties-list>})
//即对上步的过程,新节点和关系都可以增加属性
CREATE (n:学生{姓名='李四'})-[relation:LIKES{程度:'十分喜爱'}]->(m:老师{姓名='唐老师'})
⭐️注意点:与上一种新增一样是新增节点,不是原有的节点,就如例子来说,如果你已经有了一个姓名为“李四”的学生节点,并不是说运行之后就将原来的节点之间新建联系,而是新建节点在建联系,虽然属性都一样,但是id不一样,注意区别。
现有节点添加关系
MATCH (<node1-label-name>:<node1-name>),(<node2-label-name>:<node2-name>)
CREATE
(<node1-label-name>)-[<relationship-label-name>:<relationship-name>]->(<node2-label-name>)
RETURN <relationship-label-name>
match (n:student),(m:teacher)
where n.name='王二' and m.name='张三' //增加限制,可不加
create (n)-[r:likes]->(m)
return n,r,m
where是限制条件,可不加。
如果likes关系以及存在,不会新增一个likes关系,但是该添加的关系属性值都为空。
因为name这个属性并不是唯一,所以可能添加的关系不止一个,如果根据id查,则一定唯一。
match (n:student),(m:teacher)
where id(m)=144076 and id(n)=144122
create (n)-[r:likes]->(m)
return n,r,m
查找命令(match)
⭐️match命令后必须与return等命令一起使用,直接使用match命令后不跟return会报错,跟着其他命令例如create也不会。
查找节点及相关信息
- 查找节点
MATCH (<node-name>:<label-name>)
//where子句可以省略。
WHERE {
<Property1-name> = <Property1-Value>
........
<Propertyn-name> = <Propertyn-Value>
}
RETURN <node-name>
match (n:学生) where n.姓名='王二' return n
- 查找节点下的所有标签
//查询“王二”节点的所有标签
MATCH (a:学生) where a.姓名='王二' RETURN labels(a)
- 查找节点下的所有属性值
//获取“王二”节点的所有属性值
MATCH (a:学生) where a.姓名='王二' RETURN properties(a)
- 查找节点下的所有属性键
//获取“王二”节点的所有属性键
MATCH (a:学生) where a.姓名='王二' RETURN keys(a)
- 查找和当前节点有关系的节点
//查找王二所有有关系的老师的姓名
MATCH (n:学生 { 姓名 : '王二' })-->(m:老师)
RETURN m.姓名
//查找王二所有喜欢的老师的姓名
MATCH (n:学生 { 姓名 : '张三' })-[r:LIKES]->(m:老师)
RETURN m.姓名
//查询王二喜欢或不喜欢的老师的姓名
MATCH (n:学生 { 姓名 : '张三' })-[r:LIKES|DISLIKES]->(m:老师)
RETURN m.姓名
⭐️ {}修饰和where子句修饰是一个意思,只是两种表示形式的问题
查找关系
- 获取节点间关系
//查询王二和张三老师间的关系类型 (LIKES)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return type(r)
- 查找关系的所有属性值
//获取“王二”节点的所有属性值 (程度:非常喜欢)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return properties(r)
- 查找节点下的所有属性键
//获取“王二”节点的所有属性键 (程度)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return keys(r)
删除节点和关系(delete/remove)
关键字
- DELETE操作用于删除节点和关联关系。
- REMOVE操作用于删除标签和属性。
⭐️要删除节点前,将所有相关该节点的关系全部删除才能删除该节点
删除节点所有的相关关系
//删除所有王二节点的相关关系
MATCH (n:学生{姓名:'王二'})-[r]-()
DELETE r
⭐️注意关系后的是“ - ”,不是“ -> ”,在创建关系时必须指定方向,不然会报错
😄扩展
- 删除节点的所有的向外关系
//删除所有王二节点的向外关系
MATCH (n:学生{姓名:'王二'})-[r]->()
DELETE r
- 删除节点的所有向内关系
//删除所有王二节点的向外关系
MATCH ()-[r]->(n:老师{姓名:'王二'})
DELETE r
删除某个节点的某类关系
//删除王二节点的所有的LIKES类型的关系
MATCH (n:学生{姓名:'王二'})-[r:LIKES]-()
DELETE r
删除实体的属性
//删除王二学生的地址字段
MATCH (n:学生{姓名:'王二'})
REMOVE n.地址
删除所有节点和关系
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
DELETE n,r
删除Property Keys
如何去除Property Keys–删库
- 暂停服务;
- 选择安装目录,/data/databases路径下,删除 graph.db 目录;
- 重启服务。
😢不知道怎么能再不删除所有节点和关系的情况下,删除历史遗留的Property Keys,强迫症患者表示很难受,希望有知道的小伙伴分享一下
修改实体(set)
修改节点属性
//修改王二的名字
MATCH (n:学生{姓名:'王二'})
SET n.姓名='王八'
修改节点的标签
//修改王二的学生标签改为青年
MATCH (n:学生{姓名:'王二'})
REMOVE n:学生
SET n:青年
修改关系的类型
//修改王二学生对张三老师的LIKES为HATES
MATCH (n:学生)-[r:LIKES]-(m:老师)
WHERE n.姓名='王二' and m.姓名='张三'
CREATE (n)-[r2:HATES]->(m)
DELETE r