基础概念
Neo4j 采用属性图(Property Graph)模型,这是图数据库中最常用的数据模型。理解节点、关系和属性的概念是掌握 Neo4j 的基础。
核心概念
节点(Node)
节点是图中的基本实体,表示现实世界中的对象,如人、地点、物品等。
节点的组成:
- 标签(Label):用于对节点进行分类,一个节点可以有多个标签
- 属性(Property):存储在节点上的键值对数据
-- 创建一个带有标签和属性的节点
CREATE (p:Person {name: '张三', age: 30, city: '北京'})
在这个例子中:
Person是标签name、age、city是属性张三、30、北京是属性值
关系(Relationship)
关系连接两个节点,表示它们之间的关联。关系是有方向的,从起始节点指向目标节点。
关系的组成:
- 类型(Type):关系的类别,使用大写字母命名
- 方向(Direction):关系的指向(单向或双向)
- 属性(Property):关系也可以有属性
-- 创建两个节点并建立关系
CREATE (a:Person {name: '张三'})-[:FRIEND {since: '2020-01-01'}]->(b:Person {name: '李四'})
在这个例子中:
FRIEND是关系类型since是关系的属性- 关系从张三指向李四
属性(Property)
属性是存储在节点或关系上的键值对,用于描述实体或关系的特征。
支持的数据类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| String | 字符串 | 'Hello' |
| Integer | 整数 | 42 |
| Float | 浮点数 | 3.14 |
| Boolean | 布尔值 | true, false |
| Date | 日期 | date('2024-01-01') |
| DateTime | 日期时间 | datetime('2024-01-01T12:00:00Z') |
| List | 列表 | [1, 2, 3] |
| Map | 映射 | {key: 'value'} |
图模型示例
让我们通过一个社交网络的场景来理解图模型:
-- 创建人物节点
CREATE (zhangsan:Person {name: '张三', age: 30})
CREATE (lisi:Person {name: '李四', age: 28})
CREATE (wangwu:Person {name: '王五', age: 32})
-- 创建城市节点
CREATE (beijing:City {name: '北京', population: 21000000})
CREATE (shanghai:City {name: '上海', population: 24000000})
-- 创建关系:居住在
CREATE (zhangsan)-[:LIVES_IN]->(beijing)
CREATE (lisi)-[:LIVES_IN]->(shanghai)
CREATE (wangwu)-[:LIVES_IN]->(beijing)
-- 创建关系:朋友
CREATE (zhangsan)-[:FRIEND {since: '2020-01-15'}]->(lisi)
CREATE (lisi)-[:FRIEND {since: '2019-06-20'}]->(wangwu)
这个图模型包含:
- 节点:3 个人物节点,2 个城市节点
- 关系:3 个 LIVES_IN 关系,2 个 FRIEND 关系
- 属性:每个节点和关系都有相应的属性
可视化表示
上述数据在 Neo4j Browser 中可视化后,会显示为:
[张三:Person] ---FRIEND---> [李四:Person]
| |
LIVES_IN LIVES_IN
| |
[北京:City] [上海:City]
^
|
LIVES_IN
|
[王五:Person]
路径(Path)
路径是一系列节点和关系的序列,表示图中两个节点之间的连接。
-- 查询从张三到王五的路径
MATCH path = (zhangsan:Person {name: '张三'})-[:FRIEND*1..3]-(wangwu:Person {name: '王五'})
RETURN path
这个查询会返回从张三到王五的所有路径,包括经过中间节点的路径。
模式(Pattern)
模式是描述图结构的模板,用于匹配图中的子图。Cypher 使用模式进行查询。
基本模式语法:
-- 节点模式
(n:Label {property: value})
-- 关系模式
-[r:TYPE {property: value}]->
-- 完整模式
(a:Person)-[:FRIEND]->(b:Person)
命名规范
标签命名
- 使用大驼峰命名法(PascalCase)
- 使用名词单数形式
- 示例:
Person、Company、Product
关系类型命名
- 使用大写字母,下划线分隔
- 使用动词或动词短语
- 示例:
FRIEND、WORKS_FOR、BELONGS_TO
属性命名
- 使用小驼峰命名法(camelCase)
- 使用名词或形容词
- 示例:
firstName、createdAt、isActive
数据建模原则
1. 选择合适的粒度
将现实世界中的实体映射为节点时,要考虑粒度。过于细粒度会增加复杂性,过于粗粒度会丢失信息。
-- 好的设计:地址作为属性
CREATE (p:Person {name: '张三', address: '北京市海淀区'})
-- 更好的设计:地址作为节点(如果需要查询住在同一区的人)
CREATE (p:Person {name: '张三'})-[:LIVES_IN]->(d:District {name: '海淀区'})
2. 使用标签分类
合理使用标签对节点进行分类,便于查询和索引。
-- 一个节点可以有多个标签
CREATE (n:Person:Employee:Manager {name: '张三'})
3. 关系方向的设计
虽然关系有方向,但在查询时通常可以忽略方向(使用 -- 而不是 -->)。设计时要考虑业务语义。
-- 朋友关系通常是双向的
CREATE (a)-[:FRIEND]->(b)
CREATE (b)-[:FRIEND]->(a)
-- 或者查询时不考虑方向
MATCH (a:Person)-[:FRIEND]-(b:Person)
练习
- 创建一个电影数据库的图模型,包含电影、演员、导演等实体
- 设计电商系统的图模型,包含用户、商品、订单等实体
- 思考:什么时候应该将数据建模为节点,什么时候应该建模为属性?
下一步
掌握了基础概念后,继续学习 Cypher 查询语言,了解如何操作图数据。