知识图谱入门
Neo4j
1. 什么是Neo4j
Neo4j是一个基于图形数据库的开源项目,专门用于存储和查询图形数据。它使用图形结构来表示数据,其中节点表示实体,边表示实体之间的关系。这种结构使得Neo4j非常适合处理复杂的关系数据,如社交网络、推荐系统和知识图谱等。
2. Neo4j的存储方式
Neo4j使用节点,关系,属性来存储数据。

- 节点(Node):

- 表示图中的实体,并由标签标记。每个节点可以有一个或多个标签,标签用于分类节点。例如,图中节点标签为"person"和"actor"
- 节点可以有属性,属性是键值对,用于存储节点的具体信息。例如,一个人的节点可能有属性“name”和“born”。
- 被索引并受约束
- 关系(Relationship):
- 提供两个节点间的命名链接,必须有起始节点和结束节点。
- 关系也可以有属性,用于存储关系的具体信息。例如,一个“WORKS_FOR”关系可能有属性“since”,表示某人从什么时候开始在某公司工作。
- 必须有方向
- 节点可以拥有多种类型的多个关系。
- 属性(Property):
- 属性是键值对,用于存储节点和关系的具体信息。属性可以是字符串、数字、布尔值等类型。
Cypher查询语言
Cypher是Neo4j的查询语言,类似于SQL,但专门用于图形数据库。它使用模式匹配的方式来查询图形数据,允许用户通过描述图形结构来获取所需的信息。
1. 基本表示法
Cypher最核心的思想是:把图中的结构直接写在查询语句里。
- 节点用圆括号表示
1 | (n) |
表示一个节点,n 是变量名,后续可以通过它访问节点属性。
- 标签写在节点后面
1 | (n:Person) |
表示一个标签为 Person 的节点。一个节点可以有多个标签:
1 | (n:Person:Student) |
- 属性写在花括号中
1 | (n:Person {name: 'Alice', age: 20}) |
- 关系用方括号表示,箭头表示方向
1 | (a)-[r:KNOWS]->(b) |
表示 a 通过 KNOWS 关系指向 b。其中:
r是关系变量名KNOWS是关系类型->表示关系方向
如果不关心方向,也可以写成:
1 | (a)-[r:KNOWS]-(b) |
创建关系时必须指定方向,但查询时可以不指定。
2. 最常用的查询子句
Cypher中最常见的几个子句如下:
MATCH:按模式匹配图中的节点和关系WHERE:增加过滤条件RETURN:返回查询结果CREATE:创建节点和关系MERGE:如果不存在就创建,存在就复用SET:修改属性或标签DELETE/DETACH DELETE:删除节点或关系WITH:把前一步结果传递给下一步ORDER BY、LIMIT:排序和限制返回数量
一个典型查询的结构通常如下:
1 | MATCH (p:Person)-[:ACTED_IN]->(m:Movie) |
3. 查询节点
查询所有 Person 节点:
1 | MATCH (p:Person) |
按属性查询:
1 | MATCH (p:Person {name: 'Alice'}) |
也可以把条件写在 WHERE 中:
1 | MATCH (p:Person) |
4. 查询关系和路径
查询某个人认识谁:
1 | MATCH (a:Person {name: 'Alice'})-[:KNOWS]->(b:Person) |
查询两跳关系:
1 | MATCH (a:Person {name: 'Alice'})-[:KNOWS]->()-[:KNOWS]->(c:Person) |
查询一条完整路径:
1 | MATCH path = (a:Person)-[:KNOWS]->(b:Person) |
5. 可变长度路径
Cypher可以很方便地表示“走几步关系”。
1 | MATCH (a:Person {name: 'Alice'})-[:KNOWS*1..3]->(b:Person) |
这里 *1..3 表示沿着 KNOWS 关系走 1 到 3 步。它常用于:
- 查找朋友的朋友
- 查找上下游依赖
- 查找知识图谱中的多跳关联
6. 创建数据
创建一个节点:
1 | CREATE (p:Person {name: 'Alice', age: 20}) |
创建两个节点和它们之间的关系:
1 | CREATE (a:Person {name: 'Alice'}) |
也可以一次写完:
1 | CREATE (a:Person {name: 'Alice'})-[:KNOWS]->(b:Person {name: 'Bob'}) |
7. MERGE:避免重复创建
CREATE 是无条件创建,执行一次就会新增一次数据;MERGE 更像“若不存在则创建”。
1 | MERGE (p:Person {name: 'Alice'}) |
创建关系时也常和 MERGE 配合使用:
1 | MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}) |
这是实际使用中非常重要的一个子句,因为知识图谱构建时通常要避免重复节点和重复关系。
8. 修改属性
使用 SET 修改属性:
1 | MATCH (p:Person {name: 'Alice'}) |
一次设置多个属性:
1 | MATCH (p:Person {name: 'Alice'}) |
新增标签:
1 | MATCH (p:Person {name: 'Alice'}) |
9. 删除数据
删除关系:
1 | MATCH (:Person {name: 'Alice'})-[r:KNOWS]->(:Person {name: 'Bob'}) |
删除节点:
1 | MATCH (p:Person {name: 'Alice'}) |
如果节点仍然连着关系,直接 DELETE 会失败,此时要用:
1 | MATCH (p:Person {name: 'Alice'}) |
10. 聚合、排序与分页
Cypher支持常见的聚合函数,例如:
count()avg()sum()max()min()
例如统计每部电影的演员数量:
1 | MATCH (p:Person)-[:ACTED_IN]->(m:Movie) |
11. WITH 的作用
WITH 类似于“中间结果传递”。当查询分成多步时非常有用。
例如先找出演员数量大于 3 的电影,再返回电影名:
1 | MATCH (p:Person)-[:ACTED_IN]->(m:Movie) |
12. Cypher 与 SQL 的思维差异
Cypher和SQL都用于查询数据,但思路不同:
- SQL更关注“表、行、列”
- Cypher更关注“节点、关系、路径”
在关系数据库中,查询多表关系往往依赖 JOIN;而在图数据库中,关系本身就是一等公民,因此可以直接沿着边进行匹配:
1 | MATCH (p:Person)-[:WORKS_FOR]->(c:Company) |
这也是图数据库特别适合知识图谱、社交网络和推荐系统的原因之一。
