跳到主要内容

基础概念

Neo4j 采用属性图(Property Graph)模型,这是图数据库中最常用的数据模型。理解节点、关系和属性的概念是掌握 Neo4j 的基础。

核心概念

节点(Node)

节点是图中的基本实体,表示现实世界中的对象,如人、地点、物品等。

节点的组成

  • 标签(Label):用于对节点进行分类,一个节点可以有多个标签
  • 属性(Property):存储在节点上的键值对数据
-- 创建一个带有标签和属性的节点
CREATE (p:Person {name: '张三', age: 30, city: '北京'})

在这个例子中:

  • Person 是标签
  • nameagecity 是属性
  • 张三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)
  • 使用名词单数形式
  • 示例:PersonCompanyProduct

关系类型命名

  • 使用大写字母,下划线分隔
  • 使用动词或动词短语
  • 示例:FRIENDWORKS_FORBELONGS_TO

属性命名

  • 使用小驼峰命名法(camelCase)
  • 使用名词或形容词
  • 示例:firstNamecreatedAtisActive

数据建模原则

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)

练习

  1. 创建一个电影数据库的图模型,包含电影、演员、导演等实体
  2. 设计电商系统的图模型,包含用户、商品、订单等实体
  3. 思考:什么时候应该将数据建模为节点,什么时候应该建模为属性?

下一步

掌握了基础概念后,继续学习 Cypher 查询语言,了解如何操作图数据。