本章包含了完整的,权威的Cypher查询语言文档
简介
简短的介绍可以查阅Section 3.1.1, “What is Cypher?, 查看Section 2.2, “Get started with Cypher”.获得Cypher初始了解,更多术语查阅 Appendix B, Terminology.
- 什么是Cypher
- graph更新和查询
- 事物
- Uniqueness(独特性)
什么是Cypher
Cypher是一个声明式的图形查询语言(graph query language) ,它能有效的表达对图的更新和查询。它被设计于对开发人员和操作的专业人员都适用。Cypher旨在设计为一个简单切功能强大的图查询语言。特别复杂的数据库查询语言用Cypher可以很简单的表达,您只需要关注您的领域,而不会迷失在数据库访问中。
Cypher受到许多不同方法和表达式查询的启发。许多关键字,如 WHERE
和ORDER BY 是受到了SQL的启发。模型匹配借用了SPARQL的表达。一些语法借用于Haskell 和 Python.
Structure(结构)
Cypher从SQL中借用了它的结果-使用不同的字句查询。
字句被连接在一起,并且他们相互之间提供中间结果。例如,来自于MATCH匹配的变量是下一个子句的输入
查询语言由若干个子句组成。在后面的部分你会看到更多详细的信息。
这里有一些子句从图形中读取数据:
- MATCH:图形模型匹配。这是从图形中获取数据最常的方式。
- WHERE:它本身不是一个子句,而是MATCH,
OPTIONAL MATCH
和WITH的一部分。添加限制到模型,或者通过WITH过滤中间结果
- RETURN:返回
想象一下类似于下面这张图的例子:
Figure 3.1. Example Graph
创建数据语句(译者添加):
创建节点
CREATE (:People{name:"John"})
CREATE (:People{name:"Joe"})
CREATE (:People{name:"Sara"})
CREATE (:People{name:"Steve"})
CREATE (:People{name:"Maria"})
维护关系
MATCH (a:People{name:"John"}) MATCH (b:People{name:"Joe"}) CREATE (a) -[:friend]->(b)
MATCH (a:People{name:"John"}) MATCH (b:People{name:"Sara"}) CREATE (a) -[:friend]->(b)
MATCH (a:People{name:"Joe"}) MATCH (b:People{name:"Steve"}) CREATE (a) -[:friend]->(b)
MATCH (a:People{name:"Sara"}) MATCH (b:People{name:"Maria"}) CREATE (a) -[:friend]->(b)
例如,在返回“John”和找到的任何朋友的朋友之前,有一个查询会找到一个名为“John”和“John’s”的用户的朋友(虽然不是他的直接朋友)。
MATCH (john {name: 'John'})-[:friend]->()-[:friend]->(fof)
RETURN john.name, fof.name
接下来我们添加过滤到更多的查询部分:
我们获取一个用户列表并从这个列表中通过name找到所有的节点,匹配他们的朋友,只返回那些拥有以“S”开头的"name"属性的用户
MATCH (people) - [:friend] -> (follower) where people.name in ['Joe', 'John', 'Sara', 'Maria', 'Steve']
and follower.name =~ "S.*" return people.name , follower.name
返回结果
这里有些子句的例子用于去更新图:
- CREATE(和DELETE):创建和删除节点或关系
- SET(和REMOVE): 在节点上使用SET设置属性,用REMOVE进行移除
- MEGRE:匹配已经存在或创建新的节点和模型。
查询和更新图
Cypher既能更新也能查询图
更新查询的结构
- Cypher的查询部分不能同时查询和更新图形
- 每个部分都可以在图形上进行读取和匹配,或更新它
如果你从graph中读取然后更新graph,那么你的查询包含两部分---第一部分是读,第二部分是写
如果你的查询仅执行读,Cypher会进行懒加载直到你需要实际返回数据的时候才会执行。在更新查询中,在实际的写操作方省钱所有的读取操作均已完成。
当你第一次读和写时这个查询部分模型是隐式的。这部分使用WITH切分成独立的两部分。WITH就像一个切线,它将计划和这个计划完成之前分开。
当你想要使用聚合数据进行过滤时,你必须要将两个读查询部分连接在一起---> 第一部分做聚合,第二部分从第一部分的结构中过滤
match (n {name:"John"}) - [:friend] ->(friend) with n,
count(friend) as friendsCount
where friendsCount>3
return n,friendsCount
使用WITH,你将指定聚合如何发生并且聚合在Cypher过滤之前就已经完成。
这里有一个例子更新图,写一个聚合结果到图中:
MATCH (n {name: 'John'})-[:FRIEND]-(friend)
WITH n, count(friend) AS friendsCount
SET n.friendsCount = friendsCount
RETURN n.friendsCount
返回数据
任何查询都可以返回数据。如果你的查询执行读取,它已经返回数据---如果不这么做没有任何意义,并且他不是一个有效的Cypher查询。更新图的查询不会返回任何东西,但是制作读取的查询是可以的。
所有查询的之后最终都会有一个RETURN子句。RETURN不是任何查询语句的一部分---它是查询末尾的终端符号。RETURN子句有三个子句:SKIP/LIMIT 和 ORDER BY
如果您从刚刚删除的查询返回节点或关系——请注意,您持有的指针不再有效。
事物(Transactions)
任何更新图的查询都将在事物中运行,一个更新查询要么全部成功,要么全部失败。
Cypher要么创建一个新的事物要么运行在已经存在事物里面。
- 如果在运行的上下文中不存在事物,那么Cypher在查询一旦完成后就会进行提交
- 如果在正在运行的上下文中已经存在事务,那么查询将在其中运行,在成功提交该事务之前,不会将任何东西持久化到磁盘。
可以将多个查询当做一个事物提交:
- 打开事物
- 运行多个更新Cypher查询
- 提交
注意查询将维持在内存中直到整个查询已经完成执行。因此,一个大的查询需要大量的JVM heap空间
在REST API上使用事物 查阅Section 5.1, “Transactional Cypher HTTP endpoint”.
Uniqueness
当模型匹配时,在单个模型中相同的graph中Neo4j确保不会被多次匹配,在大多数场景中,这么做非常有用
例如:查找一个用户朋友的朋友返回
CREATE (adam:User { name: 'Adam' }),(pernilla:User { name: 'Pernilla' }),(david:User { name: 'David'
}),
(adam)-[:FRIEND]->(pernilla),(pernilla)-[:FRIEND]->(david)
它将返回下面的一张图给我们
现在让我们查一下Adam朋友的朋友
MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-()-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName
+---------+
| fofName |
+---------+
| "David" |
+---------+
1 row
在这个查询中,Cypher不会返回在相同的图不返回r1,r2的关系。
如果查询需要返回用户,可以用多个MATCH子句进行传播,就像:
MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend)
MATCH (friend)-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName
+---------+
| fofName |
+---------+
| "David" |
| "Adam" |
+---------+
2 rows
下面的语句和之前的第一个语句类似
MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend),(friend)-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName
这个语句中,MATCH的单个模型保护两条路径
+---------+
| fofName |
+---------+
| "David" |
+---------+
1 row
参考资料
https://neo4j.com/docs/developer-manual/current/cypher/#cypher-intro