Neo4j的Cypher语言具有以下特点:
- 声明性模式匹配语言
- 遵循SQL语法
- 语法非常简单并且人性化、可读的格式
第一章 基础
注释
注释符 //
参数
Cypher支持带参数的查询,这样就不必必须使用字符串来构建查询了。
举个简单的例子:
match (a) where a.name = $name return n
等价于
match (a {name: $name})
$name可以通过所使用的驱动来提交上去。
运算符
- 数学运算符
+、-、*、/、%、^ - 比较运算符(同时支持链式比较)请记住没有==
=、<>、<、>、<=、>=、is null、is not null - 布尔运算符
and、or、xor、not - 字符串运算符
+、=~ - 列表运算符
+、in -
属性运算符(已删除)
?、!
第二章 模式
模式和模式匹配是Cypher的操作对象。相当于在白板上画出图的形状,模式在match、create和merge等语句后出现。
- 节点模式
最简单的表达,(a)或者() - 关系节点的模式
后续不需要使用节点时,可以不给变量名 (a)-->(b)或者(a)-->() - 描述关系
(1)如果不关心关系的方向的时候,箭头可以省略,如 (a)--(b)或者 (a)-->(b)
(2)如果后续需要使用关系,可以给关系起个变量名,如 (a)-[r]->(b)
(3)在查询已经存在的数据的时候,如果关系的类型可以是一个类型集中的任意一种,可以用 | 间隔,如 (a)-[r:TYPE1|TYPE2]-(b)
(4)描述路径的长度,左右边界二者可任缺,并且也可以限制路径的类型,如 (a)-[*2]->(b) 或者 (a)-[:is_a*3..5]->(b) 或者 (a)-[*3..]->(b) 或者 (a)-[*..5]->(b) 或者 (a)-[*]->(b)
第三章 列表
列表基本操作
//列表
[0,1,2,3,4,5]
//生成0到10的列表(和python不一样)
range(0,10)
//取列表某个元素
range(0,10)[3] //取值
range(0,10)[-3] //反向取值
range(0,10)[0..3] //切片,左右索引可缺省,类似python
//size()获取列表长度
size(range(0,10)[0..3])
列表生成式
return [x in range(0,10) where x%2 = 0 | x^3] as result
运行结果是
运行结果
create 命令
(1) 创建节点和属性数据
//创建一个单标签结点
create (p:Person{name:'Owen',age:23}) //注意这里的p只是创建节点的一个临时的变量名,毫无意义
//创建一个多标签的节点
create (p:Person:Student)
(2) 创建关系
直接创建关系
create (a:Person{name:'周杰伦'})-[r:妻子]->(b:Person{name:'昆凌'}) return a,b,r
在已有节点上创建关系
match (a:Person),(b:Person) where a.name = '昆凌' and b.name = '周杰伦' create (a)-[c:嫁给了]->(b) return a,b
match-return 命令
(1) 查找有关节点和属性数据
//查找所有Person标签的节点
match (p:Person) return p
//查找所有Person标签的节点的姓名
match (p:Person) return p.name
(2) 查找关系
match (a)-[r]->(b) return a,b,r
where 命令
用法和SQL一样,很简单,起到过滤的作用
match (p:Person) where p.name = 'Owen' return p
match (p:Person) where not p.name = 'Owen' return p
match (p:Person) where p.name = 'Owen' return distinct p
with 命令
with命令和return命令很相似,区别是with语句并不是完成查询,而是为后面的部分准备输入
//collect()将所有满足值聚集在一个列表中
match (p:Person)-[:ACTED_IN]->(m:Movie)
with p, count(*) as appearances, collect(m.title) as movies
where appearances > 1
return p.name, appearances, movies
delete 和 remove 命令
- delete是删除节点或者关系
- remove是移除节点或者关系的属性、标签
//删除节点
match (p:Person) where p.age<30 delete p
//删除节点及其之间的关系
match (a:Star{name:'周杰伦'})-[r]->(b:Model{name:'昆凌'})
delete a,b,r
return a,b,r
//删除某个节点的某个属性
match (a:Person) remove a.name return a
set 命令
添加或者修改节点或者关系的属性,和remove反过来
//给节点增加属性
match (a:Person{name:'李伟'}) set a.englishname = 'Li Wei' return a
order by 命令
用于排序,默认升序,使用desc改为降序
//按照升序
match (s:Student) return s.name, s.score order by s.score
接下来的命令,使用下数据:
create (n:Person{name:'付洋', age:23, school:'wust'}),
(m:Person{name:'夏林旭', age:25, school:'wust'}),
(p:Worker{name:'付洋', age:23, dept:'IT'}),
(q:Worker{name:'李伟', age:30, dept:'产品经理'}),
(s:Worker{name:'夏林旭', age:25, dept:'产品经理'})
union 和 union all 命令
将两个结果集合并,要求列名一致,列的数据类型一样
另外,as可以给列起别名。
//方法一
match (m:Person) return m.name as name, m.age as age
union
match (n:Worker) return n.name as name, n.age as age
//方法二
match (m:Person) return m.name, m.age
union
match (m:Worker) return m.name, m.age
//错误方法
match (m:Person) return m.name, m.age
union
match (n:Worker) return n.name, n.age
//解释:return后面的变量名就是列名,所以m.name和n.name不一样,union必须保证列名一样,数据类型一样
那么对于一个不存在的列名,比如Worker不存在school属性,那么就会返回null
match (m:Person) return m.name, m.age, m.school
union
match (m:Worker) return m.name, m.age, m.school
运行结果
另外,看一下union all的使用方法,只需要对比
match (m:Person) return m.name
union all
match (m:Worker) return m.name
match (m:Person) return m.name
union
match (m:Worker) return m.name
union all的运行结果
union的运行结果
就可以看出来,union all不具备过滤重复行的功能,它是返回两个结果集所有行,并形成一个单一的结果集。
limit 和 skip
还记得sql语句中的limit使用方法吗,两种使用方法分别是limit 23和 limit 0, 23,但是在NoSQL中就只有第一种了。
和limit的顺序相反,skip是从底部计数的
merge 合并 = create + match
相当于如果图中存在就直接返回,没有就创建并返回
merge (q:Worker{name:'夏林旭', age:25, dept:'产品经理'}) return q
merge (q:Worker{name:'张真练', age:25, dept:'产品经理'}) return q
merge (q:Worker{name:'夏林旭', age:25, dept:'产品经理'}) return q
//merge允许添加额外的属性
merge (m:Movie {title:'Cloud Atlas'})
on create set m.released = 2012
return m
总结一下,merge用于向图中添加东西是很安全的,不用检查是否已经存在
in
id是节点和关系默认的内部属性,每创建一个节点或者关系,服务器都将为内部使用分配一个数字,并且自动递增。节点和关系是分开的两套id
CAPTION 标题
显示图的时候,显示出来的属性对应着CAPTION,如果CAPTION为name,那么就显示name
关系
neo4j只支持创建单向的关系,而且必须有方向。但是在查询时可以不带方向。
//创建的时候必须单向
create (a)-[]->(b)
//查询的时候无视方向
match (a)-[]-(b) return a,b
关系的数量
(a)-[*2]->(b) //长度为2
(a)-[*3..5]->(b) //长度最小3,最大5
函数篇
字符串函数
字符串函数有四个,分别是LOWER(), UPPER(), SUBSTRING(), REPLACE()
match (a:Person) return UPPER(a.school), LOWER(a.school), SUBSTRING(a.school, 0, 1), REPLACE(a.school, 'w', 'BBB')
很简单,运行结果就不贴图了
聚合函数 aggregation
个人理解,就是一些功能性的函数,可以通过return返回
match (p:Worker) return count(*)
match (p:Worker) return max(p.age), min(p.age), avg(p.age), sum(p.age)
也很简单,一看就懂,略过
关系函数
startnode(), endnode()
create (p:Star{name:'周杰伦'})-[r:marry]->(q:Model{name:'昆凌'})
match (a)-[r]->(b) return startnode(r).name, endnode(r).name, id(r), type(r)
运行结果
unique 约束
//添加unique约束
create constraint on (p:Person) assert p.name is unique
//消除unique约束
drop constraint on (p:Person) assert p.name is unique
特殊操作符?和!
//如果没有name属性,直接返回true
where p.name ? = 'foo'
//如果没有name属性,直接返回false
where p.name!= ‘foo’
正则表达式~=
//返回名字以a开头的人
match (p:Person) where p.name ~= 'a.*'
case表达式
case表达式相当于if-else分支语句
准备三个城市节点:湖北武汉,湖北黄石,以及浙江杭州。
//节点特定的某个属性做分支操作:湖北省的节点,直接返回城市名,其余省的城市返回省名+城市名
match (city)
return
case city.province
when '湖北'
then city.name
else
city.province + '-' + city.name
end
as result
运行结果
//对节点的任意属性分别做判断
match (city)
return city.name,
case
when city.name = '武汉'
then '太好了,是武汉'
when city.province = '湖北'
then '好歹也是湖北'
else
'什么也不是'
end
as result
image.png
Cypher示例
//查找和Tom Hanks同出演过电影的人
match (tom:Person {name:'Tom Hanks'})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(CoActor) return CoActor
//查找与Kevin Bacon存在4条以内关系的任何演员和电影
match (bacon:Person {name:'Kevin Bacon'})-[*1..4]-(hollywood) return distinct hollywood
//查找两个节点之间的最短关系路径
match p = shortestPath((bacon:Person{name:'Kevin Bacon'})-[*]-(meg:Person{name:'Meg Ryan'})) return p
//清空数据库
match (a:Person), (m:Movie) optional match (a)-[r1]-(), (m)-[r2]-() delete a,r1,m,r2
一朝立志,日夜前行,志同道合者敬请不吝赐教。
网友评论