图数据库 Neo4j 的基本概念和查询

FreeGuideOnline 最新 2026-07-08

认识图数据库 Neo4j

当你处理的数据之间充满复杂的关联——比如社交网络中的好友关系、电商中的商品推荐路径、金融领域的欺诈交易链条——传统的关系型数据库在处理多对多、多跳查询时会暴露出性能低下、建模僵化的问题。图数据库正是为这种高度连接的数据而生。Neo4j 是目前最流行的原生图数据库,它将数据存储为节点和关系,并提供强大的查询语言 Cypher,让你能直观地表达图遍历和模式匹配。

为什么选择图数据库?

  • 直观建模:数据模型与现实世界的实体和关系一一对应,无需复杂的 Join 表。
  • 高性能关联查询:在深度超过 2 跳的关系查询中,图数据库通过无索引邻接技术保持毫秒级响应,不会像关系型数据库那样随着数据量和跳数增长而指数级下降。
  • 灵活扩展:节点和关系可以随时增加属性,不需要预先定义所有字段。
  • 内置图算法:Neo4j 提供路径查找、中心性分析、社区发现等算法,助力高级分析。

Neo4j 的核心概念

掌握四个基本要素,你就理解了 Neo4j 的顶层设计。

节点(Node)

节点代表一个实体,例如“用户”、“电影”或“城市”。在图中通常用圆圈表示。

  • 每个节点可以有一个或多个标签(Label),用来分组。例如 :Person:Movie
  • 节点可以携带属性(Property),以键值对的形式存储数据,如 {name: "Alice", age: 30}

关系(Relationship)

关系连接两个节点,表示它们之间的行为或联系。关系是有方向性的,但也可以在查询时忽略方向。

  • 关系必须有一个类型(Type),如 :ACTED_IN:FOLLOWS
  • 和节点一样,关系也可以包含属性,例如关系上的 {since: 2020}
  • 关系始终有一个起始节点和一个结束节点。

属性(Property)

属性是键值对,节点和关系都可以拥有。值类型支持数字、字符串、布尔、列表等。属性是 Neo4j 中实际存储的数据单元。

标签(Label)

标签用于对节点进行分类、建立索引和定义约束。一个节点可以有多个标签,例如 :Person:Employee,这使得节点可以参与多种角色。

路径(Path)

路径由一系列用关系连接起来的节点组成,可以是一跳(直接相连),也可以是多跳。Cypher 查询的本质就是寻找匹配特定模式的路径。

安装与启动 Neo4j

推荐使用 Neo4j Desktop 或 AuraDB(免费云实例)快速上手。

  1. 下载 Neo4j Desktop 并安装。
  2. 创建本地数据库,设置密码,然后点击“Start”启动。
  3. 打开 Neo4j Browser,这是一个内置的 Web 查询界面,输入 :play start 可获取指引。

你也可以通过 Docker 启动:

docker run -d --name neo4j \
  -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/test1234 \
  neo4j:latest

浏览器访问 http://localhost:7474 登录即可。

Cypher 查询语言入门

Cypher 是一种声明式、模式匹配型的图查询语言,其设计灵感来源于 ASCII 艺术。你可以在画布视觉化地表达你想寻找的图模式。

基本语法元素

元素 写法示例 含义
节点 (n) 无标签匿名节点
带标签的节点 (p:Person) 标签为 Person 的节点,赋给变量 p
带属性的节点 (p:Person {name: "Tom"}) 属性 name 为 "Tom" 的 Person 节点
有向关系 (p)-[:KNOWS]->(f) 从 p 到 f 的 KNOWS 关系
无向关系 (p)-[:KNOWS]-(f) 任意方向的 KNOWS 关系
可变跳数关系 (p)-[:KNOWS*1..3]-(f) 1 到 3 跳的 KNOWS 路径

创建数据

我们先创建一个简单的社交网络:两个人互相关注。

// 创建节点
CREATE (alice:Person {name: "Alice", age: 30})
CREATE (bob:Person {name: "Bob", age: 25})

// 创建关系
MATCH (a:Person {name: "Alice"}), (b:Person {name: "Bob"})
CREATE (a)-[:FOLLOWS {since: 2021}]->(b)
CREATE (b)-[:FOLLOWS {since: 2022}]->(a)

也可以合并创建:

CREATE (alice:Person {name: "Alice"})-[:FOLLOWS {since: 2021}]->(bob:Person {name: "Bob"})

使用 MERGE 避免重复

MERGE 相当于“匹配或创建”,它检查模式是否存在,不存在则创建。适合确保实体唯一。

MERGE (city:City {name: "London"})
ON CREATE SET city.country = "UK"

基础查询

匹配节点并返回

// 查找所有 Person 节点
MATCH (p:Person)
RETURN p.name, p.age

带关系的查询

// 谁关注了 Alice?
MATCH (follower:Person)-[:FOLLOWS]->(alice:Person {name: "Alice"})
RETURN follower.name

使用 WHERE 过滤

// 查找年龄大于 28 的人
MATCH (p:Person)
WHERE p.age > 28
RETURN p.name

多跳查询(朋友的朋友)

// 找到 Alice 关注的人所关注的人,但不包含 Alice 自己以及她已直接关注的人
MATCH (alice:Person {name: "Alice"})-[:FOLLOWS]->(fof)-[:FOLLOWS]->(fof_follow)
WHERE NOT (alice)-[:FOLLOWS]->(fof_follow) AND fof_follow <> alice
RETURN DISTINCT fof_follow.name

聚合与排序

支持常用的聚合函数 COUNT, SUM, AVG, MIN, MAX

// 每人被多少人关注
MATCH (p:Person)<-[:FOLLOWS]-(f)
RETURN p.name, COUNT(f) AS followerCount
ORDER BY followerCount DESC

最短路径查询

Neo4j 内置了最短路径算法函数,用于快速找到两个节点之间的最短路径。

// 找到 Alice 与某个用户之间的最短关系路径
MATCH (a:Person {name: "Alice"}), (b:Person {name: "某人名字"}),
      path = shortestPath((a)-[:FOLLOWS*]-(b))
RETURN path

删除数据

// 删除关系
MATCH (a:Person {name: "Alice"})-[r:FOLLOWS]->(b:Person {name: "Bob"})
DELETE r

// 删除节点(需先删除所有关联关系,或用 DETACH DELETE 级联删除关系)
MATCH (obsolete:Person)
WHERE obsolete.name = "Bob"
DETACH DELETE obsolete

索引和约束

为了提高查询性能并确保数据完整性,可以为标签的属性建立索引和唯一性约束。

// 创建唯一性约束(自动建立索引)
CREATE CONSTRAINT FOR (p:Person) REQUIRE p.name IS UNIQUE

// 创建索引(非唯一)
CREATE INDEX FOR (p:Person) ON (p.age)

约束会阻止插入重复的 name 值,索引会加速基于 age 的范围查询。

实战案例:电影推荐图

使用 Neo4j 内置的示例数据集 :play movie-graph 可以快速体验。其模型包含 :Person, :Movie 节点和 :ACTED_IN, :DIRECTED, :REVIEWED 等关系。

  • 查找 Tom Hanks 出演的电影:
    MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(movie)
    RETURN movie.title
    
  • 推荐“共演关系”——与 Tom Hanks 合作过的演员还演过哪些电影:
    MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(coActor),
          (coActor)-[:ACTED_IN]->(otherMovie)
    RETURN DISTINCT otherMovie.title
    LIMIT 10
    

常见问题与最佳实践

  • 关系方向:创建时方向很重要,但查询时可以通过 ()--() 忽略方向,()-[]->() 指定方向。
  • 属性类型:选择合适的类型,不要将需要范围查询的数值存为字符串。
  • 大事务批处理:大量数据导入时使用 USING PERIODIC COMMITneo4j-admin import 工具。
  • 避免笛卡尔积:在 MATCH 左侧开始用具有较小基数的节点,并提供标签和索引字段。
  • 使用参数化查询:在应用程序中不要拼接字符串,使用 $param 传递变量,既安全又可缓存执行计划。

总结

Neo4j 将高度关联的数据转化为直观的图模型,配合 Cypher 语言使复杂的关系查询变得简洁而高效。掌握了节点、关系、属性、标签这四个基石,以及 CREATE, MATCH, RETURN, WHERE 等核心查询语句,你就已经能解决大部分图分析场景。接下来可以深入探索图数据建模、性能调优和内置图算法库 GDS,让图数据库的价值最大化。