初识Neo4j之Cypher(三)
一、介绍
Cypher 是 Neo4j 的声明式查询语言,兼容 GQL 标准。通过 openCypher 项目,Cypher 以开源方式提供。它类似于 SQL,但专为图数据优化。
Cypher 直观且接近自然语言,它采用类似 ASCII 艺术风格的语法,以可视化的方式来匹配模式和关系:
(:nodes)-[:ARE_CONNECTED_TO]->(:otherNodes)
圆括号用于表示 (:Nodes),而 -[:ARROWS]→ 用于表示 (:Nodes) 之间的关系。通过这种查询语法,你可以对图进行创建、读取、更新或删除(CRUD)操作。
二、语法
上图表示:“Sally喜欢图表。萨莉和约翰是朋友。萨莉为Neo4j工作。”
用Cypher写同样的信息:
(:Sally)-[:LIKES]->(:Graphs)
(:Sally)-[:IS_FRIENDS_WITH]->(:John)
(:Sally)-[:WORKS_FOR]->(:Neo4j)
1、节点
在属性图模型中,主要的组成部分是节点和关系。节点通常用来表示数据模型中的名词或对象。在前面的例子中,Sally、John、Graphs 和 Neo4j 都是节点。在 Cypher 中,你可以用括号将节点括起来来表示它,例如 (node)。这些括号对应于可视化中构成节点的圆圈。
1)节点标签
节点可以通过标签进行分组,用户能够指定要查找或创建的特定类型的实体。标签还帮助 Cypher 区分不同的实体,并优化查询的执行效率。在这个例子中,Sally 和 John 都可以归为 Person标签,Graphs 可以加上 Technology标签,Neo4j 则可以标记为 Company标签。
在关系数据库上下文中,这相当于告诉SQL在哪个表中查找特定的行。就像让SQL从person表中查询一个人的信息一样,用户也可以让Cypher只检查该信息的person标签。(如果没有为Cypher指定一个标签来过滤不匹配的节点类别,查询将检查数据库中的所有节点。在非常大的图数据中,这可能会影响性能。)
2)节点变量
这里有必要将匹配到的数据实体绑定到变量,以便在后续的子句中引用它们。变量可以是单个字母或单词,并且应当用小写字母书写。例如,如果你想把所有带有 Person 标签的节点绑定到变量 p,可以写作 (p:Person)。
MATCH (p:Person)
RETURN p
2、关系
图数据库的一个优点是,你可以以关系的形式存储元素(节点)之间是如何关联的信息。在 Cypher 中,关系用方括号和一个箭头来表示,连接两个节点(例如 (Node1)-[]→(Node2))。在例子中,包含 :LIKES、:IS_FRIENDS_WITH 和 :WORKS_FOR 的线条,表示节点之间的关系。
关系类型前面一定要加上冒号。如果忘记加冒号,写成 (:Person)-[LIKES]->(:Technology),那么 [LIKES] 就表示一个关系变量,而不是关系类型。
举例:
-
(:Person)-[:LIKES]->(:Technology)
这里:LIKES
表示一种关系类型,查询的是“喜欢”这种关系。 -
(:Person)-[LIKES]->(:Technology)
这里LIKES
没有冒号,Cypher 会把它当作一个关系变量(可以起任意名字,不一定叫 LIKES),而不是“喜欢”这种类型的关系。因此,这种写法只能匹配任何类型的关系,然后把这条关系赋值给变量 LIKES。
1)关系方向
关系总是具有方向性的,这通过箭头来表示。
(1)从左到右:
(p:Person)-[:LIKES]->(t:Technology)
(2)从右到左:
(p:Person)<-[:LIKES]-(t:Technology)
(3)无方向的:
MATCH (p:Person)-[:LIKES]-(t:Technology)
2)无方向关系
无方向的关系并不意味着关系本身没有方向,而是指在查询时可以从任意方向遍历。用户不能创建没有方向的关系,但在查询时可以以无方向的方式进行。
在查询中使用无方向关系特别适用于不知道关系方向的情况,因为如果用错方向写查询,Cypher 是不会返回任何结果的。因此,Cypher 会检索所有通过指定关系类型连接的节点,无论其方向如何。
注:因为查询中的无向关系被遍历两次(每个方向一次),相同的模式将返回两次。这可能会影响查询的性能。
3)关系类型
关系类型对关系进行分类并赋予其含义,类似于标签对节点的分组。按最佳实践,关系类型通常使用动词或其变体。关系类型描述了节点之间是如何关联的。这样,Cypher 查询语言几乎就像自然语言一样,节点是主语和宾语(名词),而关系(动词)则是连接它们的动作词。
在前面的例子中,关系类型有:
[:LIKES] —— 表示 Sally(一个节点)喜欢 graphs(另一个节点)。
[:IS_FRIENDS_WITH] —— 表示 Sally 和 John 是朋友。
[:WORKS_FOR] —— 表示 Sally 为 Neo4j 工作。
4)关系变量
变量在关系中可以像在节点中一样使用。一旦你为关系指定了变量,就可以在后续的查询中引用这个关系。
比如这个例子:MATCH (p:Person)-[r:LIKES]->(t:Technology) RETURN p, r, t
这个查询为节点标签(p 表示 Person,t 表示 Technology)以及关系类型(r 表示 :LIKES)都指定了变量。在 return 子句中,你就可以使用这些变量(即 p、r 和 t)来返回绑定的实体。
3、属性
属性值既可以添加到节点,也可以添加到关系上,并且可以是多种不同的数据类型。属性用花括号{}括起来,键后面跟一个冒号,值用单引号或双引号括起来:
CREATE (p:Person {name:'Sally'})-[r:IS_FRIENDS_WITH]->(p:Person {name:'John'})
RETURN p, r
4、模式
图模式匹配是 Cypher 的核心。它是一种通过声明式模式来在图中导航、描述和提取数据的机制。(p:Person {name: "Sally"})-[r:LIKES]->(g:Technology {type: "Graphs"}) 这段 Cypher 代码表示的是一个模式,但它并不是一个完整的查询。它仅仅表达了这样一个事实:有一个 name 属性为 Sally 的 Person 节点,通过 LIKES 关系,连接到了一个 type 属性为 Graphs 的 Technology 节点。要想基于这个模式执行实际操作,比如将它添加到图中或从图中查询出来,你需要在数据库中执行查询。
可以用 CREATE 子句将这条信息写入数据库:
CREATE (p:Person {name: "Sally"})-[r:LIKES]->(t:Technology {type: "Graphs"})
当数据已经写入数据库后,可以用如下模式将其查询出来:
MATCH (p:Person {name: "Sally"})-[r:LIKES]->(t:Technology {type: "Graphs"}) RETURN p, r, t