1. 前置知识:什么是图? #
在数学和计算机科学中,图(Graph)是由节点(Node)和边(Edge)组成的数据结构。在日常生活中,我们经常使用图:
- 社交网络:人是节点,朋友关系是边
- 地图:地点是节点,道路是边
- 网页链接:网页是节点,超链接是边
2. 节点(Node) #
2.1 什么是节点? #
节点是图数据库中的"点",是构成图结构的基本单元,每一个节点通常对应现实世界中的一个实体或事物。比如每个人、每家公司、每本书、每部电影、每个城市都可以在图中被抽象为一个节点。
2.2 节点的组成部分 #
一个完整的节点包含三个部分:
- 变量名(可选):用来引用这个节点
- 标签(可选):节点的类型,用冒号
:表示 - 属性(可选):节点的数据,用大括号
{}表示
基本语法:
(变量名:标签 {属性})2.3 节点的特点 #
- 语法表现:始终用圆括号
()包裹节点 - 标签(Label):节点可以标注一个或多个标签。标签通常是名词,类似于关系型数据库中的"表"或"类型",用于分类组织节点。例如
Person(人)、Company(公司)、Product(产品) - 属性(Property):节点可以包含任意多的属性。属性的本质是键值对(key-value pair),存储该节点的具体信息
- 用途:用于描述实体本身的所有静态、可查询的信息(例如:姓名、年龄、城市、成立日期等)
2.4 节点示例 #
() // 匿名节点,没有标签,没有属性
(:Person) // Person 类型的节点,没有属性
(:Person {name: "张三"}) // 有 name 属性的 Person 节点
(:Company {name: "Acme Corp", city: "北京"}) // 公司节点,含多个属性
(:Book:Product {title: "三体", price: 56}) // 同时有 Book 和 Product 标签的节点说明:
- 一个节点可以没有属性,也可以同时有多个标签和属性
- 节点内部信息通常通过属性表达,而节点归属是什么类别,则通过标签表达
2.5 节点标签(Label) #
标签用来对节点进行分类,类似于数据库中的"表"。
作用:
- 分类节点:将相同类型的节点归为一组
- 优化查询:帮助数据库快速定位节点
- 支持索引:可以为特定标签创建索引
示例:
(:Person) // Person 类型的节点
(:Company) // Company 类型的节点
(:Technology) // Technology 类型的节点多个标签: 一个节点可以有多个标签,表示它属于多个类别:
(:Person:Employee) // Person 和 Employee 同时为标签
(:Person:Employee:Manager) // 既是 Person,也是 Employee,还是 Manager
(:Product:Book:Imported) // 多标签,表示进口图书实际应用:
Person:Employee:表示员工Person:Customer:表示客户Person:Employee:Manager:表示经理
注意:
- 标签名区分大小写,且通常使用英文单数
- 关系本身没有标签,只有类型
2.6 节点变量(Variable) #
变量用来在查询中引用节点,就像给节点起个名字。
命名规则:
- 使用小写字母
- 可以是单个字母(如
p)或单词(如person) - 在节点定义时指定:
(变量名:标签)
示例:
(p:Person) // 变量名是 p
(person:Person) // 变量名是 person3. 关系(Relationship) #
3.1 什么是关系? #
关系是图数据库的第二大基本元素,代表两个节点之间的某种联系、动作、事件或依赖。没有关系的节点是孤立的,只有通过关系,节点间才能连接成大图。
3.2 前置知识:为什么关系要有方向? #
在现实世界中,很多关系是有方向的:
- "张三关注李四"(单向)
- "张三喜欢这个产品"(单向)
- "张三和李四是朋友"(双向,但存储时仍需要方向)
在 Neo4j 中,所有关系都必须有方向,这有助于:
- 明确关系的语义
- 优化查询性能
- 支持复杂的图算法
注意: 即使关系是"双向"的(如朋友关系),在 Neo4j 中也需要明确方向。查询时可以使用无向模式:
(张三)-[:IS_FRIENDS_WITH]-(李四) // 无向查询,匹配任意方向3.3 关系的组成部分 #
一个完整的关系包含:
- 方向:从起始节点指向目标节点
- 类型(Type):关系的种类,用方括号
[]表示 - 属性(Property):关系的附加数据(可选)
- 变量名(可选):用来引用这个关系
基本语法:
(起始节点)-[变量名:关系类型 {属性}]->(目标节点)3.4 关系的特点 #
- 语法表现:用方括号和箭头
-[]->指示关系方向和类型,关系始终有方向性(即从一个节点指向另一个节点),可以类比"有向边" - 类型(Type):每一条关系必须指定类型(全大写,常用下划线分隔),如
IS_FRIENDS_WITH(是朋友)、WORKS_FOR(工作于)、LIKES(喜欢)、BOUGHT(购买) - 属性(Property):关系也可以携带属性,说明两者间的详细信息,例如开始时间、等级、权重等
- 唯一性:同样的两个节点间可存在多种关系,也可存多条相同类型的关系(如一人多次购买同一商品)
- 反向:关系有方向,但查询时可以忽略方向或反向检索
3.5 关系示例 #
(:Person {name:"张三"})-[:IS_FRIENDS_WITH]->(:Person {name:"李四"})
(:Person {name:"张三"})-[:WORKS_FOR {since:2020, role:"工程师"}]->(:Company {name:"小米"})
(:User {name:"Alice"})-[:LIKES]->(:Product {name:"水杯"})说明:
- 第1行是"张三"是"李四"的朋友
- 第2行表明"张三"自2020年以来以工程师身份就职于"小米"
- 第3行是"Alice"喜欢"水杯"
3.6 关系类型命名建议 #
好的关系类型示例:
-[:LIKES]-> // 喜欢
-[:WORKS_FOR]-> // 为...工作
-[:IS_FRIENDS_WITH]-> // 与...是朋友
-[:ACTED_IN]-> // 出演
-[:DIRECTED]-> // 导演不好的关系类型示例:
-[:FRIEND]-> // ❌ 应该用 IS_FRIENDS_WITH
-[:COMPANY]-> // ❌ 应该用 WORKS_FOR命名建议:
- 使用动词:
LIKES、WORKS_FOR、ACTED_IN - 使用大写字母和下划线:
IS_FRIENDS_WITH - 描述性:清楚表达关系的含义
- ❌ 避免使用名词:关系应该描述动作或状态
4. 属性(Property) #
4.1 什么是属性? #
属性是附着在节点或关系上的键值对,通过它们可以存储丰富的、结构化的信息。
4.2 属性的特点 #
- 语法表现:用大括号
{}包裹,写在节点或关系内部 - 类型:属性值可以是数字、字符串、布尔型、列表等
- 用途:节点和关系的所有具体、可查询的信息、统计分析字段等,都应作为属性存储
- 自定义:无需提前定义结构(模式灵活),不同节点、关系可有不同属性集
4.3 属性的数据类型 #
属性可以存储多种类型的数据:
- 字符串:
"张三" - 数字:
25、3.14 - 布尔值:
true、false - 列表:
["北京", "上海"] - 日期时间:
date("2024-01-01")
4.4 属性示例 #
(:Person {name: "张三", age: 30, city: "北京", isStudent: false})
(:Movie {title: "霸王别姬", year: 1993, rating: 9.6})
(:Person)-[:WORKS_FOR {since:2018, fulltime:true}]->(:Company)
// 关系属性举例
()-[:IS_FRIENDS_WITH {since:2010, close:true}]->()说明:
- 属性可混合数字、字符串、布尔值,且无数量限制
- 节点、关系属性同语法,均为
属性名: 属性值形式
4.5 节点属性 vs 关系属性 #
节点属性:描述实体本身的特征
(:Person {name: "张三", age: 25}) // 人的姓名和年龄关系属性:描述关系的特征
(张三)-[:WORKS_FOR {since: 2020, salary: 10000}]->(公司) // 工作关系的开始时间和薪资5. 标签(Label) #
5.1 什么是标签? #
标签是图数据库中节点的分类标记,是声明节点"属于什么类型"的机制。
5.2 标签的特点 #
- 语法表现:用冒号
:紧跟标签名写于圆括号内,而且可有多个标签,用冒号分割 - 查询优化:标签常用于索引加速查询和限定范围(如仅查询 :Person 节点集合)
- 多标签:一个节点可同时拥有多个标签(例如某人既是员工也是经理:
(:Person:Employee:Manager))
5.3 标签示例 #
(:City) // 单标签
(:Person:Employee) // Person 和 Employee 同时为标签
(:Product:Book:Imported) // 多标签,表示进口图书注意:
- 标签名区分大小写,且通常使用英文单数
- 关系本身没有标签,只有类型
6. 模式(Pattern) #
6.1 什么是模式? #
模式是将节点、关系按照特定结构组合而成的表达式,用来描述你想查找的数据子图。它是 Neo4j 查询语言 Cypher 的核心语法之一。
6.2 模式的特点 #
- 节点-关系的组合:用
(节点)-[关系]->(节点)等形式连接,可以描述任何复杂网络结构 - 可无限扩展:节点与关系可以按需求随意组合、延长,支持多跳、多条件、多分支
- 用途极广:既能当做创建语句(CREATE),也能用作查询语句(MATCH),也常用于可视化
6.3 模式示例 #
// 查找朋友的朋友
(:Person {name:"小明"})-[:IS_FRIENDS_WITH]->(:Person)-[:IS_FRIENDS_WITH]->(:Person)
// 查找同公司员工之间的推荐网络
(:Person)-[:WORKS_FOR]->(:Company)<-[:WORKS_FOR]-(:Person)
// 查询购买了同一商品的所有用户
(:User)-[:BOUGHT]->(:Product)<-[:BOUGHT]-(:User)说明:
- 可以省略节点或关系内容,仅表达结构
- 用
*n..m可表达可变长度(n到m跳),比如-[:IS_FRIENDS_WITH*2..4]->查找2~4度好友
图模式让我们可以像画图一样表达复杂的数据关系,而不必写冗长复杂的代码。
7. 属性图模型 #
7.1 什么是属性图模型? #
属性图模型是 Neo4j 使用的数据模型,它有三个特点:
- 节点可以有属性:比如人的姓名、年龄
- 关系也可以有属性:比如朋友关系的开始时间
- 节点和关系都有标签/类型:用于分类
7.2 属性图模型的优势 #
- 灵活:无需提前定义结构,可以动态添加属性
- 直观:用节点和关系直接表示现实世界
- 高效:关系直接存储,查询性能稳定
8. 小结 #
8.1 核心概念总结 #
| 概念 | 语法 | 说明 | 示例 |
|---|---|---|---|
| 节点(Node) | (变量名:标签 {属性}) |
图中的实体 | (:Person {name: "张三"}) |
| 关系(Relationship) | -[变量名:类型 {属性}]-> |
节点之间的连接 | -[:IS_FRIENDS_WITH]-> |
| 属性(Property) | {键: 值} |
节点和关系的数据 | {name: "张三", age: 30} |
| 标签(Label) | :标签名 |
节点的分类 | :Person、:Company |
| 模式(Pattern) | (节点)-[关系]->(节点) |
节点和关系的组合 | (人)-[:朋友]->(朋友) |
8.2 关键要点 #
- 节点:用圆括号
()表示,可以有标签和属性 - 关系:用方括号和箭头
-[]->表示,必须有方向和类型 - 属性:用大括号
{}表示,可以是多种数据类型 - 标签:用冒号
:表示,用于分类节点 - 模式:节点和关系的组合,用于描述图结构
8.3 最佳实践 #
节点设计:
- 每个实体成为一个节点
- 使用标签分类节点
- 属性放在节点上
关系设计:
- 实体间的关系使用有向关系表示
- 关系类型使用动词
- 关系的特征放在关系属性上
属性设计:
- 属性应添加到最相关的节点或关系上
- 实体特征放在节点,关系特征放在关系