图数据库
使用图结构抽象表示和存储关系数据,并基于图结构进行语义操作(包括查询)的技术。
分类
按照底层采用存储技术不同:
- 原生图存储类
采用非关系模型,针对图数据进行了性能优化,一般采用免邻接索引进行图数据存储,可以很好的支持原生图处理引擎进行图数据计算。
- 非原生图存储类
底层采用键值数据库、文档数据库、列族数据库或者其他类型通用数据库存储图数据,通常需要建立全局索引来提高图数据访问性能。
图数据存储逻辑架构
就是图数据存储模型,基础数据为:节点(Node)、关系(Relationship)、属性(Property)
- 节点(Nodes) 节点是图数据库中的基本数据单元,通常用于表示实体,如人、地点、物品等。每个节点可以包含一个或多个属性,用于描述该节点。节点的存储通常会包括其唯一标识符、属性数据以及指向关联关系的指针。
- 关系(Relationships) 关系用于连接不同节点,表示节点之间的关联。关系也可以具有属性,用于描述关系本身的特征。关系的存储通常包括它们的类型、指向连接的起始节点和结束节点的指针以及关系属性。
- 属性(Properties) 属性是与节点和关系相关联的数据。它们用于存储关于节点和关系的详细信息,例如姓名、年龄、地址等。属性通常以键-值对的形式存储,key是字符串类型数据,value可以是多种数据类型。
另外为了提高数据访问性能及满足数据库管理要求,还包括:索引、图遍历操作算法、路径、配置参数等数据。
标签
是类别的概念,可以理解为关系数据库中表的概念,通过标签可以找到同类型的节点和关系。
一个节点可以有零或多个类别标签,一个关系必须有且仅有一个类别标签。
免邻接索引
免邻接索引的实现机制是neo4j(原生图数据库)底层存储结构设计的核心技术。
将关系预先保存到关系列表中来保证关系查询的性能,数据库中每个节点都会维护与他相邻节点的引用。
属性图模型
它扩展了传统的图数据模型,允许节点和关系具有附加属性信息。在属性图模型中,每个节点和关系都可以包含属性,这些属性是键-值对,用于描述节点和关系的详细信息。
neo4j采用属性图对数据建模,对图数据要素的表示如下:
- 节点 圆形表示,对应实体;节点标签名称一般是名词词汇。
- 关系 节点与节点间的有向边表示,实体间关联关系表现为节点关系;关系类型名称一般是表示动作的词汇。
- 属性 分为节点属性和标签属性,分别写在节点中和边旁边。
- 标签 分为节点标签和关系标签,节点标签一般以矩形框标在节点上,关系标签写在边旁边。一般以冒号开头。
CQL(cypher query language)进行neo4j数据操作技术
节点操作
1.创建
- 创建没有属性的
create (<node-name>:<label-name>);
node_name可省略
- 创建包含属性的
create (
<node-name>:<label-name>
{
<property1-name>:<property1-value>,
...
<propertyn-name>:<propertyn-value>
}
);
- 拓展:
返回节点信息 node-name为n return n;
多标签属性< node-name>:< label-name>:< label-name>
使用unwind子句展开一个集合为一个列表,一次创建多个节点
unwind [{name:"bb",age:11},{name:"aa",age:12}] as row
create (n:<label_name>)
set n.name = row.name,n.age = row.age
return n;
使用with子句(承上启下)和foreach,一次创建多个节点
with ["a","b"] as coll
foreach (value in coll | create(:Person{name:value}))
调用时间函数,创建带有时间属性的句子
with apoc. date. format
(timestamp(),'ms','yyyy-MM-dd HH:mm:ss','CTT') as createTime
create(testnode:TestNode {pro:"test",createTime:createTime})
return testnode;
2.查找
修改和删除都会用到
match(<node-name>:<label-name>)
where <condition> [<boolean-operator> <condition>]
return
<node-name>:<property1-name>,
...
<node-name>:<propertyn-name>
其中<condition>=<property-name> <comparison-operator> <value>
- 查询举例
where子句,可以使用正则表达式模糊匹配
match(peach:Movie)
where peach.released>=1990 AND peach.released<2000
return peach.title;
调用apoc库函数,查询节点的标签
match(n{name:"tom"})
return apoc.node.labels(n);
查找具有指定lebel的节点
match(n:People)
return n;
查看节点或关系的属性键
match(a)
where a.name="changtao"
return keys(a);
- 返回处理
LIMIT限制返回个数,SKIP跳过结果
match(a:Person)
return a
SKIP3
LIMIT 5;
UNION合并结果
match(pp:Person)
return pp.age,pp.name
UNION
match(pp:Customer)
return pp.age,pp.name
3.修改
set子句更新节点的标签和属性,和match配合使用
match(a)
where id(a)=7
set a.name="peach",a.age=19 修改属性/ set a:Lover 增加标签
return a;
create(tao{name:"tao",age:19})
create(peach{name:"peach",age:20})
match(a{name:"tao"}),(b{name:"peach"})
set a=b
return a,b;
4.删除
delete删除节点和关系,remove删除标签和属性,两者需和match配合使用
match(e:Employee)
delete e;
match(n{name:"peach"})
remove n:Person:Strudent; / remove n.age;
必须先删除节点相关关系后,再删除该节点。
5.merge子句
当模式存在时,匹配该模式,当模式不存在时,创建新的模式。
merge(peach:Person{name:"peach"})
return peach;
可以在merge子句后显式指定on create和on match子句,用于修改匹配的节点或关系的属性。
merge(peach:Person{name:"peach"})
on create set peach.created = timestamp() //找到匹配的节点不会执行on create
return peach.name,peach..created;
on match子句更改已经存在于数据库中节点的属性值。
关系操作
表示形式
StartNode -[Variable:RelationshipType{key1:value1,...}]-> EndNode
1.创建
必须指定关系类型(关系标签)
- 创建没有属性的
create
(<node1-Variable-name>:<node1-label-name>)
-[<Relationship-Variable-name>:<Relationship-label-name>]
-> (<node2-Variable-name>:<node2-label-name>)
return
<Relationship-Variable-name>
关系的开始节点和终止节点可以和match子句配合找到指定节点,再通过变量引用相应节点创建关系,也可以在创建关系时直接创建节点。
示例:
创建关系时创建节点
create
(a:book{name:"aa"})
-[r:base]
-> (b:book{name:"bb"});
变量引用相应节点创建关系
match(a:person),(b,movie)
where a.name="aa" and b.title="bb"
create
(a)-[r:base]-> (b)
return r;
如果没有where子句,创建关系时会在任意开始节点和终止节点之间都建立关系,创建完全图。
match(a:Student),(b:Book)
create(a)-[r:Read]->(b)
return a,b,r;
- 创建包含属性的
create
(<node1-Variable-name>:<node1-label-name> {<define-property-list>})
-[<Relationship-Variable-name>:<Relationship-label-name> {<define-property-list>}]
-> (<node2-Variable-name>:<node2-label-name> {<define-property-list>})
return
<Relationship-Variable-name>
直接创建
create(a:Person{name:'peach'})
-[r:Read{author:'jessie'}]->
(b:Book{name:'fool'})
return a,b,r;
匹配已有节点
match(a:Person),(b:Movie)
where a.name='jessie' and b.title = 'funny'
create(a)-[s:See{role:['forest']}]->(b)
return r;
2.查找
关系分为两种:"--"(忽略关系类型和方向),"->""<-",分别表示有无方向。
特殊表达:
一般需要在()加上节点变量名称、标签名称、属性列表等限定条件,[]内加上关系变量名称、关系类型名称或关系属性列表等限定条件。
()--(); 一切关系
()->(); 单向关系
()-[]-() 可设定关系约束的一切关系
()-[]->() 可设定关系约束的一切单向关系
- 举例
查询所有关系,返回关系类型
match()-[r]-()
return r,type(r);
查询与peach有关系的节点
match(p:Person)--(q)
where p.name = 'peach'
return q;
查询peach出演的电影
match(p:Person{name:'peach'})-[r:Act_in]->(m:Movie)
return m.name;
查询与电影abc有关的人员节点及其关系,输出人员、关系类型、关系各个属性值。
match(p:Person)-[a]-(m:Movie{name:'abc'})
return p.name,type(a),a;
查询和peach同时参演abc的演员,返回电影名称、演员名称、各自角色
match(p:Person{name:'peach'})-[a:Act_in]->(m:Movie)<-[b:Act_in]-(q:Person)
return m.name,q.name,a.role,b.role;
查询没有任何关系的节点
match(n)
where not (n)--()
return n; / return id(n); / return apoc.node.labels(n); / return properties(n)
查询我的朋友的朋友中还不是我的朋友的人
create(a:Person{name:'wang'})-[:fof]->(b:Person{name:'zhang'})-[:fof]->(b:Person{name:'li'})
match(a:Person{name:'wang'})-[:fof]-()-[:fof]-(b)
where not (a)-[:fof]-(b)
return b.name;
推荐还没和peach合作过的演员,推荐强度按照被查到的次数降序排序统计输出
match(p:Person{name:'peach'})-[:Act_in]->(m1)<-[:Act_in]-(coActors),
(coActors)-[:Act_in]->(m2)<-[:Act_in]-(cocoActors)
where not p-[:Act_in]->()<-[:Act_in]-(cocoActors) and p <> cocoActors
return cocoActors.name as recommended,count(*) as strength
order by strength DESC;
查询能帮助peach引荐jessie 的以前和他们都合作过的演员
match(p:Person{name:'peach'})-[:Act_in]->(m1)<-[:Act_in]-(coActors),
(coActors)-[:Act_in]->(m2)<-[:Act_in]-(q:Person{name:'jessie'})
return p,m1,coActors,m2,q;
3.修改
主要指关系属性的修改,可以增加也可以修改。
create(n:Student{name:'wang'})-[s:Study]->(c:Course{name:'NOSQL'})
match(n:Student{name:'wang'})-[s:Study]->(c:Course{name:'NOSQL'})
set s.year='2024'
return s.year;
4.删除
一般配合match子句,关系及节点也可以一起删除。
delete <node1-name>,<node2-name>,<relationship-name>
remove删除关系属性remove r.roles
可以同时删除单个节点和连接它的所有关系
create(n:Student{name:'wang'})-[s:Study]->(c:Course{name:'NOSQL'})
create(c:Course{name:'database'})
match(n:Student{name:'wang'}),(c:Course{name:'database'})
create(n)-[s:Study]-(c)
match(n:Student{name:'wang'})-[r]-(c)
delete r,n,c;
删除所有节点和关系,option match表示节点可以有关系(如果有关系该命令将连带其关系一起删除)
match(n) option match(n)-[r]-()
delete n,r;