2.2 Cypher 查询语言基础 2.2 Cypher 查询语言基础详解与实践 2.2.1 Cypher 简介:声明式图查询语言 Cypher 是一种为图数据库设计的声明式查询语言。与命令式语言不同,Cypher 侧重于描述你想查询什么,而不是如何查询。这种声明式的特性使得 Cypher 语法简洁易懂,更贴近人类的自然语言,降低了学习和使用的门槛。 Cypher 的设计灵感来源于 SQL,但它针对图数据模型进行了优化。它允许我们使用图形模式来描述我们想要查找的数据,并使用简洁的语法来表达复杂的图查询。Cypher 的核心概念围绕着节点 (Nodes)、关系 (Relationships) 和 属性 (Properties),这些也是构建图数据库的基本元素。 2.2.
Cypher 是一种为图数据库设计的声明式查询语言。与命令式语言不同,Cypher 侧重于描述你想查询什么,而不是如何查询。这种声明式的特性使得 Cypher 语法简洁易懂,更贴近人类的自然语言,降低了学习和使用的门槛。
Cypher 的设计灵感来源于 SQL,但它针对图数据模型进行了优化。它允许我们使用图形模式来描述我们想要查找的数据,并使用简洁的语法来表达复杂的图查询。Cypher 的核心概念围绕着节点 (Nodes)、关系 (Relationships) 和 属性 (Properties),这些也是构建图数据库的基本元素。
在深入 Cypher 查询之前,我们需要先了解其基础语法元素,这些元素构成了 Cypher 查询语言的基石。
节点是图数据库中最基本的单元,代表着图中的实体。例如,在社交网络图中,节点可以代表用户、帖子或评论;在知识图谱中,节点可以代表概念、实体或事件。
在 Cypher 中,我们使用圆括号 () 来表示节点。例如,() 就代表一个匿名节点。我们可以给节点添加标签 (Labels) 和属性 (Properties) 来进一步描述节点。
标签 (Labels):用于对节点进行分类,一个节点可以拥有多个标签。标签可以帮助我们快速地筛选和查询特定类型的节点。标签名以字母开头,可以包含字母、数字和下划线。
属性 (Properties):用于描述节点的特征或属性,以键值对 (key-value) 的形式存储。属性的键 (key) 是字符串,值 (value) 可以是字符串、数字、布尔值、数组等数据类型。
代码实践:创建带有标签和属性的节点
// 创建一个带有 "Person" 标签和属性的节点 CREATE (p:Person {name: 'Alice', age: 30, city: 'London'}) RETURN p
内容详解:
CREATE 关键字用于创建新的节点或关系。
(p:Person {name: 'Alice', age: 30, city: 'London'}) 定义了要创建的节点模式:
() 表示创建一个节点。
p 是节点的变量名,用于在后续查询中引用该节点。
:Person 表示给节点添加 "Person" 标签。
{name: 'Alice', age: 30, city: 'London'} 定义了节点的属性,包括 name, age, 和 city 及其对应的值。
RETURN p 表示返回创建的节点 p。
Mermaid 图示:
图示说明:
图中展示了一个带有 "Person" 标签和属性 "name: Alice" 的节点。节点用圆形表示,标签显示在冒号前,属性键值对显示在冒号后。
关系连接着图中的节点,描述节点之间的联系。关系是有方向的,从一个节点指向另一个节点。例如,在社交网络图中,关系可以表示 "朋友关系"、"关注关系" 等;在知识图谱中,关系可以表示 "属于"、"包含"、"创作" 等。
在 Cypher 中,我们使用中划线和箭头 --> 或 <-- 或双向 -- 来表示关系。关系也有类型 (Relationship Types) 和属性 (Properties)。
关系类型 (Relationship Types):用于描述关系的种类,类似于节点的标签。关系类型名以大写字母开头,可以包含大写字母、数字和下划线。
属性 (Properties):与节点属性类似,用于描述关系的特征或属性。
代码实践:创建带有关系类型和属性的关系
// 创建两个 Person 节点 CREATE (alice:Person {name: 'Alice'}) CREATE (bob:Person {name: 'Bob'}) // 在 Alice 和 Bob 之间创建 "FRIENDS_WITH" 关系,并添加属性 CREATE (alice)-[r:FRIENDS_WITH {since: '2023-10-26'}]->(bob) RETURN alice, r, bob
内容详解:
首先创建了两个 "Person" 节点 alice 和 bob。
CREATE (alice)-[r:FRIENDS_WITH {since: '2023-10-26'}]->(bob) 定义了要创建的关系模式:
(alice) 和 (bob) 分别代表关系起始节点 alice 和结束节点 bob。
-[r:FRIENDS_WITH {since: '2023-10-26'}]- 表示创建关系:
[] 表示创建一个关系。
r 是关系的变量名。
:FRIENDS_WITH 表示关系类型为 "FRIENDS_WITH"。
{since: '2023-10-26'} 定义了关系属性 since 及其值。
-> 表示关系的方向是从 alice 指向 bob。
Mermaid 图示:
图示说明:
图中展示了两个 "Person" 节点 "Alice" 和 "Bob",以及连接它们的一个 "FRIENDS_WITH" 关系。关系用箭头表示,关系类型和属性显示在箭头旁边。
属性是节点和关系的关键特征描述,以键值对的形式存在。属性可以帮助我们存储和查询关于节点和关系的具体信息。
代码实践:查询和修改属性
// 查询名为 'Alice' 的 Person 节点的年龄 MATCH (p:Person {name: 'Alice'}) RETURN p.age AS AliceAge // 修改名为 'Alice' 的 Person 节点的城市为 'New York' MATCH (p:Person {name: 'Alice'}) SET p.city = 'New York' RETURN p
内容详解:
查询属性:
MATCH (p:Person {name: 'Alice'}) 匹配标签为 "Person" 且属性 name 为 'Alice' 的节点。
RETURN p.age AS AliceAge 返回匹配到的节点 p 的 age 属性,并使用别名 AliceAge。
修改属性:
MATCH (p:Person {name: 'Alice'}) 同样是匹配节点。
SET p.city = 'New York' 使用 SET 关键字设置或更新节点 p 的 city 属性为 'New York'。
标签和关系类型是图数据库中重要的组织和分类机制。它们帮助我们对节点和关系进行分组,并根据类型进行查询和分析。
代码实践:使用标签和关系类型进行过滤查询
// 查询所有标签为 "Person" 的节点 MATCH (p:Person) RETURN p // 查询所有 "FRIENDS_WITH" 关系 MATCH ()-[r:FRIENDS_WITH]-() RETURN r // 查询 Alice 的朋友 (即有 "FRIENDS_WITH" 关系连接的 Person 节点) MATCH (alice:Person {name: 'Alice'})-[:FRIENDS_WITH]-(friend:Person) RETURN friend
内容详解:
查询标签为 "Person" 的节点:
MATCH (p:Person) 匹配所有标签为 "Person" 的节点。查询 "FRIENDS_WITH" 关系:
MATCH ()-[r:FRIENDS_WITH]-() 匹配所有类型为 "FRIENDS_WITH" 的关系,忽略起始和结束节点。查询 Alice 的朋友:
MATCH (alice:Person {name: 'Alice'})-[:FRIENDS_WITH]-(friend:Person) 匹配模式:
(alice:Person {name: 'Alice'}) 匹配名为 'Alice' 的 "Person" 节点。
-[:FRIENDS_WITH]- 匹配类型为 "FRIENDS_WITH" 的关系,方向不限 (双向)。
(friend:Person) 匹配关系的另一端,标签为 "Person" 的节点,并将其变量名设置为 friend。
Cypher 查询语句通常由多个子句组成,这些子句组合起来表达了复杂的查询逻辑。以下介绍 Cypher 中常用的基础子句:
MATCH 子句是 Cypher 中最核心的子句之一,用于在图中查找与指定模式匹配的数据。模式由节点和关系组成,可以包含标签、关系类型和属性条件。
代码实践:使用 MATCH 进行模式匹配
// 查找 Alice 的朋友的朋友 MATCH (alice:Person {name: 'Alice'})-[:FRIENDS_WITH]-(friend:Person)-[:FRIENDS_WITH]-(foaf:Person) RETURN foaf.name AS FriendOfAFriend
内容详解:
MATCH (alice:Person {name: 'Alice'})-[:FRIENDS_WITH]-(friend:Person)-[:FRIENDS_WITH]-(foaf:Person) 定义了要匹配的模式:
从名为 'Alice' 的 "Person" 节点开始 ((alice:Person {name: 'Alice'}))。
经过一个 "FRIENDS_WITH" 关系 (-[:FRIENDS_WITH]-) 到达一个 "Person" 节点 ((friend:Person))。
再经过一个 "FRIENDS_WITH" 关系 (-[:FRIENDS_WITH]-) 到达另一个 "Person" 节点 ((foaf:Person))。
RETURN foaf.name AS FriendOfAFriend 返回找到的 "朋友的朋友" 节点的 name 属性,并命名为 FriendOfAFriend。
Mermaid 图示:
图示说明:
图中展示了查询 "Alice 的朋友的朋友" 的模式。 MATCH 子句会在图中查找符合这种模式的路径。
RETURN 子句用于指定查询结果中需要返回的内容。可以返回节点、关系、属性、聚合函数的结果等。可以使用别名 (AS) 来给返回的结果命名。
代码实践:使用 RETURN 返回不同类型的结果
// 返回节点和关系 MATCH (alice:Person {name: 'Alice'})-[r:FRIENDS_WITH]-(friend:Person) RETURN alice, r, friend // 返回属性值和计算结果 MATCH (p:Person) RETURN p.name, p.age, p.age * 2 AS DoubleAge
内容详解:
返回节点和关系: 直接在 RETURN 子句中列出节点变量 alice, friend 和关系变量 r,即可返回匹配到的节点和关系。
返回属性值和计算结果: 可以返回节点的属性值,也可以对属性值进行计算,并使用 AS 关键字为计算结果命名别名。
WHERE 子句用于添加过滤条件,限制 MATCH 子句匹配的结果。可以使用各种比较运算符 (如 =, <>, <, >, <=, >=)、逻辑运算符 (AND, OR, NOT) 和函数 (如 startsWith, contains, exists) 来构建复杂的过滤条件。
代码实践:使用 WHERE 子句进行条件过滤
// 查找年龄大于 25 岁的 Person 节点 MATCH (p:Person) WHERE p.age > 25 RETURN p // 查找名字以 'A' 开头的 Person 节点的朋友 MATCH (p:Person {name: 'Alice'})-[:FRIENDS_WITH]-(friend:Person) WHERE startsWith(friend.name, 'A') RETURN friend
内容详解:
查找年龄大于 25 岁的 Person 节点:
WHERE p.age > 25 添加过滤条件,只返回 age 属性值大于 25 的节点。查找名字以 'A' 开头的 Person 节点的朋友:
WHERE startsWith(friend.name, 'A') 使用 startsWith 函数过滤,只返回 friend 节点中 name 属性值以 'A' 开头的节点。CREATE 子句用于在图中创建新的节点和关系。在前面已经演示过 CREATE 的基本用法,这里再补充一些更复杂的创建场景。
代码实践:使用 CREATE 创建多个节点和关系
// 创建多个 Person 节点和关系 CREATE (charlie:Person {name: 'Charlie', age: 28}), (david:Person {name: 'David', age: 35}), (charlie)-[:FRIENDS_WITH]->(david) RETURN charlie, david
内容详解:
CREATE 子句可以同时创建多个节点和关系,使用逗号分隔不同的创建模式。
上述例子中,同时创建了 charlie 和 david 两个 "Person" 节点,并在它们之间创建了一个 "FRIENDS_WITH" 关系。
SET 子句用于设置或更新节点和关系的属性,以及给节点添加标签。
代码实践:使用 SET 设置属性和标签
// 给名为 'Bob' 的 Person 节点添加一个新的属性 'email' MATCH (p:Person {name: 'Bob'}) SET p.email = 'bob@example.com' RETURN p // 给名为 'Charlie' 的 Person 节点添加一个标签 "Developer" MATCH (p:Person {name: 'Charlie'}) SET p:Developer RETURN p // 同时设置属性和添加标签 MATCH (p:Person {name: 'David'}) SET p.occupation = 'Engineer', p:Expert RETURN p
内容详解:
设置属性: SET p.email = 'bob@example.com' 设置或更新节点 p 的 email 属性。
添加标签: SET p:Developer 给节点 p 添加 "Developer" 标签。
同时设置属性和添加标签: 可以使用逗号分隔多个 SET 操作,一次性完成多个属性设置和标签添加。
DELETE 子句用于删除节点和关系。REMOVE 子句用于移除节点和关系的属性和标签。
代码实践:使用 DELETE 和 REMOVE 删除数据
// 删除名为 'David' 的 Person 节点及其所有关系 (慎用) MATCH (p:Person {name: 'David'}) DETACH DELETE p // 删除名为 'Bob' 的 Person 节点的 'email' 属性 MATCH (p:Person {name: 'Bob'}) REMOVE p.email RETURN p // 移除名为 'Charlie' 的 Person 节点的 "Developer" 标签 MATCH (p:Person {name: 'Charlie'}) REMOVE p:Developer RETURN p
内容详解:
删除节点和关系:
DETACH DELETE p 用于删除节点 p 以及与之关联的所有关系。 注意:删除节点会影响到与之相连的关系,需要谨慎使用 DETACH DELETE。 如果直接使用 DELETE p 且节点 p 还有关系连接,则会报错。移除属性: REMOVE p.email 移除节点 p 的 email 属性。
移除标签: REMOVE p:Developer 移除节点 p 的 "Developer" 标签。
掌握 Cypher 查询语言的基础是深入学习 Neo4j 图数据库的关键一步。在后续的学习中,我们将继续探索 Cypher 更高级的特性和应用场景,例如聚合、函数、路径查询、索引优化等,以便更有效地利用图数据库解决实际问题。
下一步学习建议:
深入学习 Cypher 的各种函数和操作符,例如字符串函数、日期函数、列表操作、聚合函数等。
掌握 Cypher 的路径查询功能,例如变长关系路径、最短路径、所有路径等。
了解 Cypher 的索引和性能优化技巧,提升查询效率。
结合实际业务场景,练习编写 Cypher 查询,加深理解和应用能力。
希望这篇文章能够帮助你迈出学习 Cypher 的第一步,开启你的图数据库探索之旅!