Neo4j之CQL基础
文章目录
一、CQL概念
关系型数据库的查询语言是SQL,Neo4j 图数据库也有自己的查询语言,那就是CQL。
CQL全称Cypher Query Language
,它是一种声明性的模式匹配语言,跟SQL非常类似,也遵循SQL的语法。
CQL的语句书写起来都非常简单,而且很人性化,可读性强。
二、CQL简介
如果熟悉SQL,那么CQL的语法很容易就学会了。 下面通过表格列出 CQL 中常用的一些命令和函数。
第一个是CQL常用命令
命令/释义 | 用途 |
---|---|
create/创建 | 创建节点、关系或属性 |
match/匹配 | 获取有关节点、关系或属性的数据 |
return/返回 | 返回最终需要的查询结果 |
where/条件 | 根据条件过滤数据 |
delete/删除 | 删除节点、关系 |
remove/移除 | 删除节点和关系的属性、标签 |
order by/排序 | 对最终结果进行排序 |
set/组 | 添加或者更新标签、属性 |
第二个是CQL常用函数
函数/释义 | 用途 |
---|---|
Aggregation/聚合 | 对查询结果执行一些聚合操作 |
Relationship/关系 | 获取关系的细节,如startnode,endnode等 |
String/字符串 | 使用字符串的功能,例如截取子串、替换等 |
三、CQL命令使用
create
create命令可以用于创建节点,有两种语法,分别对应创建无属性的节点和有属性的节点。
//无属性
create (<node-name>:<label-name>)
//有属性
create (
<node-name>:<label-name>
{
<Property1-name>:<Property1-Value>
........
<PropertyN-name>:<PropertyN-Value>
}
)
node-name是要创建的节点的具体名称,label-name是节点所属的标签的名称。即,一个标签要管理一组节点。
property-name和property-value是键值对,定义该节点的一个属性,即该属性的名称和值。
这里有个重要的点,那就是使用create命令一定会创建节点
。当创建节点时,节点内部都会自带一个ID属性,该ID的值由系统内部给一个数字,然后自动递增。所以,就算定义两个节点的属性值全部相同,但是其内部ID值一定不同,系统会将他们视为两个独立节点。
示例如下:
//在数据库中创建了两个节点zhangsan和lisi,他们都属于标签Student。
create (zhangsan:Student)
create (lisi:Student)
//创建了一个节点xiaoming,也属于标签Student,有三个属性:id、name。dept
create (
xiaoming:Student
{
id: 001,
age:20,
dept:"CS"
}
)
create也可以创建一个节点对应多个标签,语法为:
create (<node-name>:<label-name1>:<label-name2>.....:<label-nameN>)
示例:
create (xiaobai:Boy:Student:Person)
//这里xiaobai是节点名,Boy、Student、Person是该节点的多个标签名称
create还可以用于创建节点之间的关系,语法为:
create (<node1-name>:<label1-name>)-
[<relationship-name>:<relationship-label-name>]
->(<node2-name>:<label2-name>)
relationship-name是要创建的关系的具体名称,relationship-label-name是关系的标签名称。
具体示例如下,创建了两个节点,并且从节点b1到g1有一个单向的关系
create (b1:Boy)-[r1:Likes]->(g1:Girl)
注意,Neo4j中两个节点之间的关系是有方向性的
,使用了箭头进行标记:() - []→()。如果没有使用箭头标记关系的方向:() - [] - (),那么Neo4j服务器会报错。
match+return
match命令语法为:
match
(
<node-name>:<label-name>
)
这里有个很重要的注意事项,不能单独使用match语句,必须和其他语句进行配合
。如果单独使用match,系统将报错InvalidSyntax,我们使用时match经常与return配合。
return命令语法为:
return
<node-name>.<property1-name>,
······
<node-name>.<propertyN-name>
return语句也是不能单独使用的,应该与match或者create语句配合
。
match配合return语句示例:
//检索Student标签下xiaoming节点的某几个属性
match (xiaoming:Student)
return xiaoming.id, xiaoming.age
//检索Student标签下xiaoming节点的所有属性
match (xiaoming:Student)
return xiaoming
where
where命令的用法和SQL完全一样,就是通过限制条件来过滤数据
//简单where
where <condition>
//复杂where
where <condition> <boolean-operator> <condition>
condition就是筛选条件,包括小于、大于、小于等于、大于等于、等于、不等于六种选择,例如 id>100,age<=20 等。值得注意的是,不等于用 <>
来进行表示。
boolean-operator就是布尔运算符,包括 AND、OR、NOT、XOR 四种,分别对应与
、或
、非
、异或
四种操作。
示例如下,假设现在数据库中有2个年龄20岁和2个年龄21岁的学生(标签Student),名字分别是zhangsan、lisi、zhangsan、lisi。
//查询年龄为21的学生
match (stu:Student)
where stu.age=21
return stu
//查询年龄为20且名字为zhangsan的学生
match (stu:student)
whhere stu.age=20 and stu.name="zhangsan"
return stu
delete
delete的删除方式有两种,一种是直接删除节点,但是要求删除的节点不能与其他节点有关系连接;另一种是将节点和关系一起删除。
//删除节点
delete <node-namelist>
//删除节点及其关系
delete <node1-name>,<node2-name>,<relationship-name>
示例如下,这里删除的都是之前create的节点
//删除节点
match (zhangsan:Student) delete zhangsan
//删除节点及其关系
match (b1:Boy)-[r1]-(g1:Girl)
delete b1,g1,r1
remove
delete与remove的相同点:
两者都不能单独使用
两者都应该和match命令配合使用
delete和remove的不同点:
- delete用于删除节点和关系
- remove用于删除标签和属性
remove语法:
//删除节点或关系的属性
remove <property-name-list>
//删除节点或关系的标签
remove <label-name-list>
示例如下:
//先创建节点
create (stu1:Student {sid:003,name:"xiao bai",age:19,dept:"SE"})
create (xiaohong:Girl:Student:Person)
//删除“dept”属性
match (stu1{sid:003})
remove stu1.dept
return stu1
//删除student、person标签
match (xiaohong:Girl)
remove xiaohong:Student,xiaohong:Person
set
set语法:
//添加/更新属性
set <property-name-list>
示例如下:
//先创建节点
create (stu2:Student {sid:004,name:"xiao gang",age:20,dept:"SE"})
//添加属性class
match (stu2:Student)
where stu2.dept="SE"
set stu2.class = "SE01"
return stu2
//已经存在属性class,则会将其更改为SE02
match (stu2:Student)
where stu2.dept="SE"
set stu2.class = "SE02"
return stu2
order by
order by命令可以对match查询的结果进行排序,默认是升序排序。语法如下:
在语句最后使用 limit n 可以仅获取结果的前n个节点
//升序
ORDER BY <property-name-list>
//降序使用关键字 desc
ORDER BY <property-name-list> desc
示例如下,假设数据库中存在5本书(标签Book),id分别为001至005,price分别是20、40、30、50、10
//按价格升序,获取前三个节点
match (book:Book)
return book
order by book.price
limit 3
//按id降序
match (book:Book)
return book
order by book.id desc
merge
我们知道,create命令一定会创建节点,因此当我们想判断某个节点是否存在时,需要先使用match进行查询;如果存在就不用重复创建,如果不存在再使用create命令创建。
对于这种情况我们可以使用merge命令,merge命令其实就是create命令和match命令的结合。
merge命令的语法和create命令一模一样。但是merge的作用是,如果当前查询节点的属性存在,则不创建新的节点,如果属性不存在就创建新节点。
//创建新节点
merge (t1:Test{id:001, name:"hhh"})
//查询到属性值存在,不会创建节点
merge (t2:Test{name:"hhh"})
merge (t2:Test{id:001})
//查询到属性值不同,创建新节点
merge (t3:Test{id:002,name:"hhh"})
merge (t4:Test{id:003,name:"go"})
四、CQL函数使用
String
字符串常用函数一共是四个
函数 | 效果 |
---|---|
upper | 将字符串中的所有字母更改为大写字母 |
lower | 将字符串中的所有字母更改为小写字母 |
substring | 获取所给字符串的指定子字符串 |
replace | 替换所给字符串的子字符串 |
函数语法如下:
- 一个字符串长度为n,索引值的区间是 0 到 n-1。
- input-string是节点或关系的属性名称
- startIndex是开始位置的索引值,endIndex是结尾位置的索引值,
取值区间左闭右开
。endIndex可以省略,省略时默认到字符串的结尾 - StartString是要替换之前的子字符串,endString是要替换的字符串
upper (<input-String>)
lower (<input-string>)
substring (<input-string>,<startIndex> ,<endIndex>)
replace (<input-string>,<startString> ,<endString>)
示例如下:
create (
b:Book
{
name:"WildGrass",
price:30
}
)
//结果为 WILDGRASS、wildgrass、wild、HomeGrass
match (b:Book)
return upper(b.name),lower(b.name),substring(b.name,0,4),replace(b.name,"Wild","Home")
这里需要注意,b.name的值一直是“WildGrass”。因为字符串函数用在return里面都作用于查询的数据,不会更改数据库中节点属性原本的值。
Aggregation
聚合函数的用法和SQL中完全一致
函数 | 效果 |
---|---|
count | 统计match命令返回的行数 |
max | 找到match命令返回的一组行中的最大值 |
min | 找到match命令返回的一组行中的最小值 |
sum | 统计match命令返回的一组行的值求和 |
avg | 统计match命令返回的一组行的值求平均值 |
函数语法如下:
count(<value>) //<value>可以是*,节点或关系标签名称或属性名称
max(<property-name>)
min(<property-name>)
sum(<property-name>)
avg(<property-name>)
示例如下,假设数据库中存在5本书(标签Book),id分别为001至005,price分别是20、40、30、50、10
//结果为5
match (book:Book) return count(*)
//结果为50、10、150、50
match (book:Book)
return max(book.price),min(book.price),sum(book.price),avg(book.price)
Relationship
CQL的关系函数可以在获取开始节点,结束节点等细节时知道该关系的细节。
函数 | 效果 |
---|---|
startnode | 获取关系的开始节点 |
endnode | 获取关系的结束节点 |
id | 获取关系的ID |
type | 获取关系的类型信息 |
这里的 id 就是我们在create命令中提到的内部ID。
函数语法如下:
- relationship-label-name是来自节点或关系的属性名称
- relationship-name是关系名称
startnode (<relationship-label-name>)
endnode (<relationship-label-name>)
id (<relationship-name>)
type (<relationship-name>)
示例如下:
//先创建关系
create (b101:Boy)-[r101:Likes]->(g101:Girl)
create (s201:Student)-[r201:Read]->(b201:Book)
//获取指定关系的开始和结束节点
match (b)-[r:Likes]->(g)
return startnode(r),endnode(r)
//获取指定关系的id和type
match (s)-[r:Read]->(b)
return id(r),type(r)
//如果不指定关系,那么将会把所有类型的关系都查询出来
match (b)-[r]->(g)
return id(r),type(r)