Neo4j Cypher查询语言详解.docx
《Neo4j Cypher查询语言详解.docx》由会员分享,可在线阅读,更多相关《Neo4j Cypher查询语言详解.docx(33页珍藏版)》请在冰豆网上搜索。
Neo4jCypher查询语言详解
Neo4jCypher查询语言详解
?
Cypher介绍
“Cypher”是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询。
Cypher还在继续发展和成熟,这也就意味着有可能会出现语法的变化。
同时也意味着作为组件没有经历严格的性能测试。
Cypher设计的目的是一个人类查询语言,适合于开发者和在数据库上做点对点模式(ad-hoc)查询的专业操作人员(我认为这个很重要)。
它的构念是基于英语单词和灵巧的图解。
Cyper通过一系列不同的方法和建立于确定的实践为表达查询而激发的。
许多关键字如like和orderby是受SQL的启发。
模式匹配的表达式来自于SPARQL。
正则表达式匹配实现实用Scalaprogramminglanguage语言。
Cypher是一个申明式的语言。
对比命令式语言如Java和脚本语言如Gremlin和JRuby,它的焦点在于从图中如何找回(whattoretrieve),而不是怎么去做。
这使得在不对用户公布的实现细节里关心的是怎么优化查询。
这个查询语言包含以下几个明显的部分:
▪START:
在图中的开始点,通过元素的ID或所以查找获得。
▪MATCH:
图形的匹配模式,束缚于开始点。
▪WHERE:
过滤条件。
▪RETURN:
返回所需要的。
在下例中看三个关键字
示例图片如下:
如:
这个有个查询,通过遍历图找到索引里一个叫John的朋友的朋友(不是他的直接朋友),返回John和找到的朋友的朋友。
STARTjohn=node:
node_auto_index(name='John')
MATCHjohn-[:
friend]->()-[:
friend]->fof
RETURNjohn,fof
返回结果:
下一步添加过滤:
在下一个例子中,列出一组用户的id并遍历图查找这些用户接出friend关系线,返回有属性name并且其值是以S开始的用户。
STARTuser=node(5,4,1,2,3)
MATCHuser-[:
friend]->follower
WHEREfollower.name=~/S.*/
RETURNuser,follower.name
返回结果:
操作符
Cypher中的操作符有三个不同种类:
数学,相等和关系。
数学操作符有+,-,*,/和%。
当然只有+对字符有作用。
等于操作符有=,<>,<,>,<=,>=。
因为Neo4j是一个模式少的图形数据库,Cypher有两个特殊的操作符?
和!
。
有些是用在属性上,有些事用于处理缺少值。
对于一个不存在的属性做比较会导致错误。
为替代与其他什么做比较时总是检查属性是否存在,在缺失属性时问号将使得比较总是返回true,感叹号使得比较总是返回false。
WHEREn.prop?
="foo"
这个断言在属性缺失情况下将评估为true。
WHEREn.prop!
="foo"
这个断言在属性缺失情况下将评估为false。
警告:
在同一个比较中混合使用两个符号将导致不可预料的结果。
参数
Cypher支持带参数的查询。
这允许开发者不需要必须构建一个string的查询,并且使得Cypher的查询计划的缓存更容易。
参数可以在where子句,start子句的索引key或索引值,索引查询中作为节点/关系id的引用。
以下是几个在java中使用参数的示例:
节点id参数
Mapparams=newHashMap();
params.put("id",0);
ExecutionResultresult=engine.execute("startn=node({id})returnn.name",params);
节点对象参数
Mapparams=newHashMap();
params.put("node",andreasNode);
ExecutionResultresult=engine.execute("startn=node({node})returnn.name",params);
多节点id参数
Mapparams=newHashMap();
params.put("id",Arrays.asList(0,1,2));
ExecutionResultresult=engine.execute("startn=node({id})returnn.name",params);
字符串参数
Mapparams=newHashMap();
params.put("name","Johan");
ExecutionResultresult=engine.execute("startn=node(0,1,2)wheren.name={name}returnn",params);
索引键值参数
Mapparams=newHashMap();
params.put("key","name");
params.put("value","Michaela");
ExecutionResultresult=engine.execute("startn=node:
people({key}={value})returnn",params);
索引查询参数
Mapparams=newHashMap();
params.put("query","name:
Andreas");
ExecutionResultresult=engine.execute("startn=node:
people({query})returnn",params);
▪SKIP与LIMIT*的数字参数
Mapparams=newHashMap();
params.put("s",1);
params.put("l",1);
ExecutionResultresult=engine.execute("startn=node(0,1,2)returnn.nameskip{s}limit{l}",params);
▪正则表达式参数
Mapparams=newHashMap();
params.put("regex",".*h.*");
ExecutionResultresult=engine.execute("startn=node(0,1,2)wheren.name=~{regex}returnn.name",params);
标识符
当你参考部分的模式时,需要通过命名完成。
定义的不同的命名部分就被称为标识符。
如下例中:
STARTn=node
(1)MATCHn-->bRETURNb
标识符为n和b。
标识符可以是大写或小些,可以包含下划线。
当需要其他字符时可以使用符号。
对于属性名的规则也是一样。
注解
可以在查询语句中使用双斜杠来添加注解。
如:
STARTn=node
(1)RETURNb//这是行结束注释
STARTn=node
(1)RETURNb
STARTn=node
(1)WHEREn.property="//这部是一个注释"RETURNb
Start
每一个查询都是描述一个图案(模式),在这个图案(模式)中可以有多个限制点。
一个限制点是为模式匹配的从开始点出发的一条关系或一个节点。
可以通过id或索引查询绑定点。
通过id绑定点
通过node(*)函数绑定一个节点作为开始点
查询:
STARTn=node
(1)
RETURNn
返回引用的节点。
结果:
通过id绑定关系
可以通过relationship()函数绑定一个关系作为开始点。
也可以通过缩写rel()。
查询:
STARTr=relationship(0)
RETURNr
Id为0的关系将被返回
结果:
通过id绑定多个节点
选择多个节点可以通过逗号分开。
查询:
STARTn=node(1,2,3)
RETURNn
结果:
所有节点
得到所有节点可以通过星号(*),同样对于关系也适用。
查询:
STARTn=node(*)
RETURNn
这个查询将返回图中所有节点。
结果:
通过索引查询获取节点
如果开始节点可以通过索引查询得到,可以如此来写:
node:
index-name(key=”value”)。
在此列子中存在一个节点索引叫nodes。
查询:
STARTn=node:
nodes(name="A")
RETURNn
索引中命名为A的节点将被返回。
结果:
通过索引查询获取关系
如果开始点可以通过索引查询得到,可以如此做:
Relationship:
index-name(key=”value”)。
查询:
STARTr=relationship:
rels(property="some_value")
RETURNr
索引中属性名为”some_value”的关系将被返回。
结果:
多个开始点
有时需要绑定多个开始点。
只需要列出并以逗号分隔开。
查询:
STARTa=node
(1),b=node
(2)
RETURNa,b
A和B两个节点都将被返回。
结果:
Match
在一个查询的匹配(match)部分申明图形(模式)。
模式的申明导致一个或多个以逗号隔开的路径(path)。
节点标识符可以使用或者不是用圆括号。
使用圆括号与不使用圆括号完全对等,如:
MATCH(a)-->(b)与MATCHa-->b匹配模式完全相同。
模式的所有部分都直接或者间接地绑定到开始点上。
可选关系是一个可选描述模式的方法,但在真正图中可能没有匹配(节点可能没有或者没有此类关系时),将被估值为null。
与SQL中的外联结类似,如果Cypher发现一个或者多个匹配,将会全部返回。
如果没有匹配,Cypher将返回null。
如以下例子,b和p都是可选的病都可能包含null:
STARTa=node
(1)MATCHp=a-[?
]->b
STARTa=node
(1)MATCHp=a-[*?
]->b
STARTa=node
(1)MATCHp=a-[?
]->x-->b
STARTa=node
(1),x=node(100)MATCHp=shortestPath(a-[*?
]->x)
相关节点
符号—意味着相关性,不需要关心方向和类型。
查询:
STARTn=node(3)
MATCH(n)--(x)
RETURNx
所有与A相关节点都被返回。
结果:
接出关系(Outgongrelationship)
当对关系的方向感兴趣时,可以使用-->或<--符号,如:
查询:
STARTn=node(3)
MATCH(n)-->(x)
RETURNx
所有A的接出关系到达的节点将被返回.
结果:
定向关系和标识符
如果需要关系的标识符,为了过滤关系的属性或为了返回关系,可如下例使用标识符。
查询:
STARTn=node(3)
MATCH(n)-[r]->()
RETURNr
所有从节点A接出的关系将被返回。
结果:
通过关系类型匹配
当已知关系类型并想通过关系类型匹配时,可以通过冒号详细描述。
查询:
STARTn=node(3)
MATCH(n)-[:
BLOCKS]->(x)
RETURNx
返回A接出关系类型为BLOCKS的节点。
结果:
通过关系类型匹配和使用标识符
如果既想获得关系又要通过已知的关系类型,那就都添加上,如:
查询:
STARTn=node(3)
MATCH(n)-[r:
BLOCKS]->()
RETURNr
所有从A接出的关系为BLOCKS的关系都被返回。
结果:
带有特殊字符的关系类型
有时候数据库中有非字母字符类型,或有空格在内时,使用单引号。
查询:
STARTn=node(3)
MATCH(n)-[r:
TYPEWITHSPACEINIT]->()
RETURNr
返回类型有空格的关系。
结果:
多重关系
关系可以通过使用在()—()多个语句来表达,或可以串在一起。
如下:
查询:
STARTa=node(3)
MATCH(a)-[:
KNOWS]->(b)-[:
KNOWS]->(c)
RETURNa,b,c
路径中的三个节点。
结果:
可变长度的关系
可变数量的关系->节点可以使用-[:
TYPE*minHops..maxHops]->。
查询:
STARTa=node(3),x=node(2,4)
MATCHa-[:
KNOWS*1..3]->x
RETURNa,x
如果在1到3的关系中存在路径,将返回开始点和结束点。
结果:
在可变长度关系的关系标识符
当连接两个节点的长度是可变的不确定的时,可以使用一个关系标识符遍历所有关系。
查询:
STARTa=node(3),x=node(2,4)
MATCHa-[r:
KNOWS*1..3]->x
RETURNr
如果在1到3的关系中存在路径,将返回开始点和结束点。
结果:
零长度路径
当使用可变长度路径,可能其路径长度为0,这也就是说两个标识符指向的为同一个节点。
如果两点间的距离为0,可以确定这是同一个节点。
查询:
STARTa=node(3)
MATCHp1=a-[:
KNOWS*0..1]->b,p2=b-[:
BLOCKS*0..1]->c
RETURNa,b,c,length(p1),length(p2)
这个查询将返回四个路径,其中有些路径长度为0.
结果:
可选关系
如果关系为可选的,可以使用问号表示。
与SQL的外连接类似。
如果关系存在,将被返回。
如果不存在在其位置将以null代替。
查询:
STARTa=node
(2)
MATCHa-[?
]->x
RETURNa,x
返回一个节点和一个null,因为这个节点没有关系。
结果:
可选类型和命名关系
通过一个正常的关系,可以决定哪个标识符可以进入,那些关系类型是需要的。
查询:
STARTa=node(3)
MATCHa-[r?
:
LOVES]->()
RETURNa,r
返回一个节点和一个null,因为这个节点没有关系。
结果:
可选元素的属性
返回可选元素上的属性,null值将返回null。
查询:
STARTa=node
(2)
MATCHa-[?
]->x
RETURNx,x.name
元素x在查询中为null,所有其属性name为null。
结果:
复杂匹配
在Cypher中,可哟通过更多复杂模式来匹配,像一个钻石形状模式。
查询:
STARTa=node(3)
MATCH(a)-[:
KNOWS]->(b)-[:
KNOWS]->(c),(a)-[:
BLOCKS]-(d)-[:
KNOWS]-(c)
RETURNa,b,c,d
路径中的四个节点。
结果:
最短路径
使用shortestPath函数可以找出一条两个节点间的最短路径,如下。
查询:
STARTd=node
(1),e=node
(2)
MATCHp=shortestPath(d-[*..15]->e)
RETURNp
这意味着:
找出两点间的一条最短路径,最大关系长度为15.圆括号内是一个简单的路径连接,开始节点,连接关系和结束节点。
关系的字符描述像关系类型,最大数和方向在寻找最短路径中都将被用到。
也可以标识路径为可选。
结果:
所有最但路径
找出两节点节点所有的最短路径。
查询:
STARTd=node
(1),e=node
(2)
MATCHp=allShortestPaths(d-[*..15]->e)
RETURNp
这将在节点d与e中找到两条有方向的路径。
结果:
命名路径
如果想在模式图上的路径进行过滤或者返回此路径,可以使用命名路径(namedpath)。
查询:
STARTa=node(3)
MATCHp=a-->b
RETURNp
开始节点的两个路径。
结果:
在绑定关系上的匹配
当模式中包含一个绑定关系时,此关系模式没有明确的方向,Cypher将尝试着切换连接节点的边匹配关系。
查询:
STARTa=node(3),b=node
(2)
MATCHa-[?
:
KNOWS]-x-[?
:
KNOWS]-b
RETURNx
将返回两个连接节点,一次为开始节点,一次为结束节点。
结果:
Where
如果需要从查找的数据的图中过滤,可以在查询语句中添加where子句。
图:
Boolean操作类型
可以使用boolean操作符and和or或者也可以使用not()函数。
查询:
STARTn=node(3,1)
WHERE(n.age<30andn.name="Tobias")ornot(n.name="Tobias")
RETURNn
返回节点。
结果:
节点属性上的过滤
查询:
STARTn=node(3,1)
WHEREn.age<30
RETURNn
结果:
正则表达式
可以通过使用=~/regexp/来匹配正在表达式。
如下:
查询:
STARTn=node(3,1)
WHEREn.name=~/Tob.*/
RETURNn
返回名叫Tobias的节点。
结果:
转义正则表达式
如果在正则表达式中需要有斜杠时可以通过转义实现。
查询:
STARTn=node(3,1)
WHEREn.name=~/Some\/thing/
RETURNn
没有匹配的节点返回。
结果:
不分大小些正则表达式
在正则表达式前加上?
i,整个正则表达式将会忽略大小写。
查询:
STARTn=node(3,1)
WHEREn.name=~/(?
i)ANDR.*/
RETURNn
属性name为Andres的节点将返回
结果:
关系类型上的过滤
可以match模式中通过添加具体的关系类型,但有时需要针对类型的更加高级的过滤。
可以使用明确的type属性来对比,查询对关系类型名作一个正则比较。
查询:
STARTn=node(3)
MATCH(n)-[r]->()
WHEREtype(r)=~/K.*/
RETURNr
关系整个以K开始的类型名都将返回。
结果:
属性存在性
查询:
STARTn=node(3,1)
WHEREn.belt
RETURNn
结果:
如果缺失属性默认为true
仅当属性存在时,比较一个图的元素的此属性,使用允许空属性的语法。
查询:
STARTn=node(3,1)
WHEREn.belt?
='white'
RETURNn
所有节点即使没有belt属性的都将返回。
此类比较返回为true。
结果:
如果缺失属性默认为false
需要在缺失属性时为false,即不想返回此属性不存在的节点时。
使用感叹号。
查询:
STARTn=node(3,1)
WHEREn.belt!
='white'
RETURNn
结果:
空置null过滤
有时候需要测试值或者标识符是否为null。
与sql类似使用isnull或not(isnullx)也能起作用。
查询:
STARTa=node
(1),b=node(3,2)
MATCHa<-[r?
]-b
WHERErisnull
RETURNb
Tobias节点没有链接上。
结果:
关系过滤
为过滤两点间基于关系的子图,在match子句中使用限制部分。
可以描述带方向的关系和可能的类型。
这些都是有效的表达:
WHEREa-→bWHEREa←-bWHEREa←[:
KNOWS]-bWHEREa-[:
KNOWS]-b
查询:
STARTa=node
(1),b=node(3,2)
WHEREa<--b
RETURNb
Tobias节点没有链接
结果:
neo4j综合
目录
1.返回节点
2.返回关系
3.返回属性
4.带特殊字符的标识符
5.列的别名
6.可选属性
7.特别的结果
?
查询中的返回部分,返回途中定义的感兴趣的部分。
可以为节点、关系或其上的属性。
图
返回节点
返回一个节点,在返回语句中列出即可。
查询:
STARTn=node
(2)
RETURNn
?
结果:
返回关系
查询:
STARTn=node
(1)
MATCH(n)-[r:
KNOWS]->(c)
RETURNr
结果:
返回属性
查询:
STARTn=node
(1)
RETURNn.name
结果:
带特殊字符的标识符
使用不在英语字符表中的字符,可以使用’单引号。
查询:
START?
Thisisn'tacommonidentifier=node
(1)
RETURN?
Thisisn'tacommonidentifier.<
!
__?
?
>>`
结果:
列的别名
可以给展示出来的列名起别名。
查询:
STARTa=node
(1)
RETURNa.ageASSomethingTotallyDifferent
?
返回节点的age属性,但重命名列名。
结果:
可选属性
属性在节点上可能存在也可能不存在,可以使用问号来标识标识符即可。
查询:
STARTn=node(1,2)
RETURNn.age?
如果存在age属性,则返回,不存在则返回null。
结果:
特别的结果
DISTINCT?
仅检索特别的行,基于选择输出的列。
查询:
STARTa=node
(1)
MATCH(a)-->(b)
RETURNdistinctb
返回name为B的节点,但仅为一次。
结果:
neo4j聚合函数
1.聚合Aggregation
1.计数
2.计算节点数
3.分组计算关系类型
4.计算实体数
5.计算非空可以值数
6.求和sum
7.平均值avg
8.最大值max
9.最小值min
10.聚类COLLECT
11.相异DISTINCT
聚合(Aggregation)
为集合计算数据,Cypher提供聚类功能,与SQL的groupby类似。
在return语句中发现的任何聚类函数,所有没有聚类函数的列将作为聚合key使用。
图:
计数
计数(count)使用来计算行数。
Count有两种使用方法。
Count(*)计算匹配的行的行数,count(<标识符>)计算标识符中非空值数。
计算节点数
计算链接到一个节点的节点数,可以使用count(*)。
查询:
STARTn=node
(2)
MATCH(n)-->(x)
RETURNn,count(*)
?
返回开始节点和相关节点节点数。
结果:
分组计算关系类型
计算分组了得关系类型,返回关系类型并使用count(*)计算。
查询:
STARTn=node
(2)
MATCH(n)-[r]->()
RETURNtype(r),count(*)
?
返回关系类型和其分组数。
结果:
计算实体数
相比使用count(*),可能计算标识符更实在。
查询:
STARTn=node
(2)
MATCH(n)-->