| 编辑推荐: |
本文详细介绍了其核心概念、安装部署方法、专用的Cypher查询语言以及如何使用Python进行连接和操作。,希望对你的学习有帮助。
本文来自于AGI舰长,由火龙果软件Alice编辑、推荐。 |
|
第 1 章 简介
图数据库(Graph Database) 是一种以图结构为基础进行数据存储与查询的数据库。与传统的关系型数据库通过表格和主外键进行建模不同,图数据库使用节点(Nodes)和关系(Relationships)直接表示实体及其之间的连接,更加自然地映射现实世界中的关联结构,特别适用于处理复杂的连接型数据。
Neo4j 是目前最流行和成熟的图数据库之一,由 Neo4j 公司使用 Java 开发。它采用原生图存储与查询引擎,广泛应用于社交网络、推荐系统、知识图谱、反欺诈分析、网络安全等领域,是构建基于连接关系应用的强大平台。
- 官方控制台
https://console-preview.neo4j.io/instance-created
- 开发者中心
https://neo4j.com/deployment-center/
- 中文文档
https://neo4j.ac.cn/docs/
第 2 章 安装
2.1 安装方式概览
Neo4j 提供了多种安装方式,以适应不同的开发和部署需求,主要包括以下三种:
本地可视化工具,适合开发者使用,界面友好,支持多项目管理,适用于学习、测试和原型开发。
通过系统安装包部署,适用于生产环境,具备更高的灵活性和控制力,适合有一定技术基础的用户。
官方提供的全托管云数据库服务,免安装、免运维,开箱即用,适合快速上线项目或对云优先策略有需求的用户。
2.2 OS Deployment
本教程选用OS Deployment方式,部署环境为Windows系统,Neo4j版本为5.26(LTS)。
2.2.1 安装JDK
Neo4j的运行需要Java环境,根据 官方文档 要求, 5.26(LTS) 版本的Neo4j需要安装JDK17或者JDK21。JDK的安装包可从 Oracle官网 下载(需注册账号并登录),或者直接从课程资料中获取。
获取安装包后,双击安装包进行安装即可。安装完毕后,可在终端执行 java --version 命令检查是否安装成功,若成功,则会输出版本信息。
2.2.2 安装包-安装Neo4j
1) 获取安装包
Neo4j 有企业版(付费)和社区版(免费)供用户选择,本课程使用社区版。安装包可从 Neo4j官网 下载,或者直接从课程资料中获取。
2) 配置环境变量
安装包获取后,须手动解压到安装目录,并添加环境变量 NEO4J_HOME ,路径指向 bin 的上一级路径,然后再在 PATH 环境变量下添加 %NEO4J_HOME%\bin 。操作完成后可在终端执行 neo4j --version 命令,如果输出版本信息,则说明操作成功。
3) 安装 neo4j service
执行如下命令,可将 eno4j 作为系统服务进行安装。
neo4j windows-service install
|
4) 启动 neo4j
初次启动,需执行如下命令,后续会开机自启。
5) 访问 web 页面
启动成功后, neo4j 会提供一个 web 页面作为客户端,访问地址为 http://localhost:7474/browser ,初始用户名和密码均为 neo4j 。初次登录需要修改密码。
docker run \
--restart always \
--publish=7474:7474 --publish=7687:7687 \
--env NEO4J_AUTH=neo4j/neo4jneo4j \
--volume=/Users/javastarboy/volume/neo4j \
neo4j:5.26
|
- 初始用户名密码 neo4j 【docker 安装的时候可以直接指定密码】,第一次登录会提示你修改密码。
- 点击 Let`s go: 然后输入用户名密码进入客户端
2.2.3 Docker 安装
用户可以访问如下链接下载适用于 macOS、Windows 和 Linux 操作系统的 Docker。 DockerHub 托管着 官方的 Neo4j 镜像 ,该镜像提供了适用于各种版本的 Neo4j 社区版和企业版的标准、即用型软件包。
- 快速开始:https://www.docker.com/get-started/
- Neo4j 镜像: https://hub.docker.com/_/neo4j
- 官方教程 https://neo4j.com/docs/operations-manual/current/docker/introduction/
2.2.3.1 获取 Neo4j 映像
Neo4j 镜像的变体根据社区版/企业版以及用作基础镜像的操作系统进行标记。
社区版和企业版均支持标签功能。
- 企业版 标签会在版本号后添加 -enterprise 后缀
- 例如: neo4j:2025.10.1-enterprise
- 最新的 Neo4j 企业版发布版本为 neo4j:enterprise
Neo4j 企业版许可证
要使用 Neo4j 企业版,您必须通过设置环境变量来接受许可协议
NEO4J_ACCEPT_LICENSE_AGREEMENT=yes 。
© Network Engine for Objects in Lund AB. 2023。版权所有。未经 Neo4j, Inc. 或其关联公司授权,禁止使用本软件。
可以使用“联系 Neo4j”表格发送电子邮件咨询。
更多信息请访问
https ://neo4j.com/licensing/
2.2.3.2 基础操作系统
Neo4j 镜像可以作为基础镜像使用
debian:bullseye-slim ,也 redhat/ubi9-minimal:latest 可以作为基础镜像使用。默认值为 debian:bullseye-slim 。
如果您不确定要使用哪个基础图像,或者没有偏好,则只需使用默认值即可
neo4j:2025.10.1 。
要指定要使用的基础图像,图像标签可以选择性地带有 -bullseye 或 -ubi9 后缀。例如:
Red Hat UBI9 变体镜像仅适用于 Neo4j 5.17.0 及更高版本。对于更早的 Neo4j 版本,请勿指定基础镜像。
2.2.3.3 使用 Neo4j Docker 镜像
您可以使用以下命令启动 Neo4j 容器。请注意,此 Neo4j 容器在重启后不会保留数据,并且将使用默认的用户名/密码。
docker run \
--restart always \
--publish=7474:7474 --publish=7687:7687 \
neo4j:2025.10.1
|
您可以通过在 Web 浏览器中打开 http://localhost:7474/ (Neo4j 的浏览器界面)来试用您的 Neo4j 容器 。默认情况下,Neo4j 需要身份验证,并在首次连接时提示您使用用户名/密码登录 neo4j/neo4j 。之后,系统会提示您设置新密码。
默认密码最小长度为 8 个字符。
使用 dbms.security.auth_minimum_password_length 配置设置更改默认最小值。
以下各节提供了有关如何设置初始密码、配置 Neo4j 以在重启之间持久化数据以及使用 Neo4j Docker 镜像的更多信息。
2.2.3.4 重启后数据仍能保留
此 --volume 选项会将本地文件夹映射到容器,以便在重启后保留数据。要在容器之间保留数据库内容,请 /data 在启动容器时将卷挂载到该目录:
docker run \
--restart always \
--publish=7474:7474 --publish=7687:7687 \
--env NEO4J_AUTH=neo4j/your_password \
--volume=/path/to/your/data:/data \
neo4j:2025.10.1
docker run \
--restart always \
--publish=7474:7474 --publish=7687:7687 \
--env NEO4J_AUTH=neo4j/neo4jneo4j \
--env TZ=Asia/Shanghai \
--volume=/Users/javastarboy/volume/neo4j \
--name neo4j \
neo4j:5.26
|
🎯 要挂载的 文件夹 必须在 启动 Docker 之前 存在 ,否则,由于权限错误,Neo4j 将无法启动。
有关挂载卷的更多信息,请参阅 使用 Docker 卷持久化数据 。
2.2.3.5 用于 NEO4J_AUTH 设置初始密码
NEO4J_AUTH 在 Docker 容器中使用 Neo4j 时,您可以通过在运行指令中 指定参数来直接设置数据库的初始密码:
docker run \
--restart always \
--publish=7474:7474 --publish=7687:7687 \
--env NEO4J_AUTH=neo4j/your_password \
neo4j:2025.10.1
|
或者,您可以通过指定 NEO4J_AUTH 以下方式禁用身份验证 none :
请注意,目前无法更改初始用户名 neo4j 。
此设置NEO4J_AUTH不会覆盖现有的身份验证。
如果您已挂载包含现有数据库的/dataNEO4J_AUTH卷,则此设置将无效,因为该数据库已配置身份验证。Neo4j Docker 服务将启动,但您需要使用已与数据库关联的用户名和密码才能登录。
2.2.3.6 实用 docker run 选项
下表列出了一些可用的选项:
该 --restart always 选项设置 Neo4j 容器(以及 Neo4j)在 Docker 守护进程重启时自动重启。
如果您不再希望容器在机器启动时自动启动,可以使用标志禁用此设置 no ,例如: docker update --restart=no <containerID> 。
有关 Docker 重启策略的更多信息,请参阅 Docker 官方文档 。
2.2.3.7 Neo4j Docker 镜像的离线安装
Docker 提供了一个 docker save 命令,可以将镜像下载到 .tar 软件包中,以便离线使用或传输到没有互联网访问权限的机器。
这是一个将 neo4j:2025.10.1 图像保存到 .tar 文件的示例命令:
- docker save -o neo4j- 2025 . 10 . 1 .tar neo4j: 2025 . 10 . 1
.tar 要从docker 创建的文件 中加载 Docker 镜像 docker save ,请使用以下 docker load 命令。例如:
- docker load --input neo4j- 2025 . 10 . 1 .tar
有关使用 ` docker save and` docker load 命令的完整说明,请参阅:
- 官方docker save文件 。
- 官方docker load文件 。
2.2.3.8 docker-compose.yml
version: '3'
services:
neo4j:
image: neo4j:5.19.0-community
container_name: neo4j
restart: always
environment:
- TZ=Asia/Shanghai
ports:
- "7474:7474"
- "7687:7687"
volumes:
- ./neo4j/data:/data
- ./neo4j/logs:/var/lib/neo4j/logs
|
第 3 章 Cypher语言基础
3.1 概述
Cypher 是 Neo4j 图数据库专用的查询语言,其语法直观清晰,设计风格与 SQL 类似,专门用于高效处理图数据。它通过高度可读的声明式语法,简化了图数据的创建、查询、更新与删除( CRUD )操作,尤其擅长表达复杂的图模式匹配。
除了基础操作, Cypher 还支持子查询、聚合计算、条件过滤以及集合操作等高级功能,是图数据库领域最核心的查询工具之一。
3.2 图数据模型
Cypher 基于 Neo4j 的图数据模型进行设计,该模型由以下三种基本元素组成:
节点代表图中的实体对象,如 “人”、“公司”、“电影”等。每个节点:
- 拥有一个或多个标签(Labels)(可选)
- 包含若干属性(Properties)(可选)
如下图所示:
Cypher 中用 ( ) 声明一个节点,具体语法如下图所示:
关系用于连接两个节点,表示它们之间的有向连接,如“人电影”,“人电影”。每个关系:
- 拥有一个类型(Type)(必须)
- 包含若干个属性(Propertie)(可选)
如下图所示:
Cypher中用 -[ ]-> 声明一个关系,具体语法如下图所示:
路径是由一系列 节点和关系连接构成的结构 ,代表图中实体间的关联链条,是图查询的核心。
3.3 写入节点
效果就不挨个截图了,在第 6 张截图几个示例
在 Cypher 中,使用 CREATE 语句创建图中的节点。每个节点可以携带一个或多个标签(如 Person 、 Actor )和一组属性(如 name 、 gender ),这些标签和属性用来标识节点的类型和具体信息。
CREATE (n1:Person:Actor:Director {name: '王宝强', gender: '男'})
CREATE (n2:Movie {title: '唐探1900', released: '2025-01-29'})
|
3.4 查询节点
在 Cypher 中,使用 MATCH 语句可以查找图中的节点。但实际上, MATCH 的作用不仅仅是“查询节点”,它的本质是匹配图中符合特定结构( Pattern )的数据。
所谓结构( Pattern ),是由节点、关系、路径等组成的图形模板。通过在 MATCH 中描述这个结构,我们可以匹配到图中已有的节点、关系或路径等信息。
MATCH (n:Person {name: '王宝强'}) RETURN n;
|
3.5 写入关系
通过 CREATE 语句也可以在两个节点之间创建关系。关系必须指定类型,也可以带上属性(例如角色名),用来表示两个实体之间的具体连接方式。
MATCH (n1:Person {name: '王宝强'}), (n2:Movie {title: '唐探1900'})
CREATE (n1)-[:ACTED_IN {role: '阿鬼'}]->(n2)
|
3.6 查询关系
在 Cypher 中,使用 MATCH 可以查找图中节点之间的关系。就像查询节点一样,我们通过编写一个图结构模式( pattern )来描述希望匹配的关系结构。
关系模式通常包括起始节点、关系方向和类型、以及目标节点。 Cypher 会根据这个结构,从图中找出所有符合条件的关系。
MATCH (n1:Person {name: '王宝强'})-[r]->(n2:Movie {title: '唐探1900'})
RETURN r
|
3.7 写入路径
在 Cypher 中,除了可以分别创建节点和关系,还可以通过一条语句同时创建多个节点和它们之间的连接关系,即写入一条完整的路径。
路径结构由节点 ( ) 和关系 -[ ]-> 组合而成,语法直观,能够更高效地表达图中的连接数据。
CREATE
(n1:Person:Actor:Singer {name: '刘德华', gender: '男'})-
[:ACTED_IN {roles: ['刘建明']}]->
(n2:Movie {title: '无间道', released: '2002-12-12'})
|
3.8 查询路径
使用 MATCH 语句也可以查询图中的完整路径结构,返回由多个节点和关系组成的连接链条。在 Cypher 中,可以使用变量(如 path )来表示路径。
MATCH path = (n1:Person)-[r:ACTED_IN]->(n2:Movie)
RETURN path
|
3.9 修改数据
在 Cypher 中,可以使用 SET 和 REMOVE 对图中的节点或关系进行修改。 SET 用于添加或更新属性,也可以为节点添加新的标签; REMOVE 用于删除属性或移除已有的标签。
MATCH (n1:Person {name: '王宝强'})
SET n1.birth = '1984-05-29', n1: Singer
|
MATCH (n1:Person {name: '王宝强'})-[r:ACTED_IN]->(n2:Movie {title: '唐探1900'})
REMOVE r.role
SET r.roles = ['阿鬼']
|
3.10 删除数据
使用 DELETE 可以删除节点和关系。在执行删除操作前,通常需要先通过 MATCH 找到对应的节点和关系。如果一个节点还有未删除的关系,必须先删除关系,才能成功删除该节点。
MATCH (n1:Person {name: '王宝强'})-[r:ACTED_IN]->(n2:Movie {title: '唐探1900'})
DELETE n1, r, n2
|
3.11 合并操作
- Merge(合并)操作相当于Match和Create操作的一个组合,其会先匹配目标节点或关系是否存在,如果不存在,则创建目标节点,如果存在则不执行任何操作。
MERGE (n2:Movie {title: '唐探1900', released: '2025-01-29'});
MERGE (n1:Person:Actor:Director {name: '王宝强', gender: '男'})
ON CREATE SET n1.create_time = datetime()
ON MATCH SET n1.update_time = datetime()
|
// Merge关系
MERGE (n1:Person {name: '王宝强'})-[r:ACTED_IN {roles: ['阿鬼']}]->(n2:Movie {title: '唐探1900'})
|
第 4 章 Cypher数据类型
Cypher 支持丰富的数据类型,以满足图数据存储与查询的多样化需求。 Cypher 中的值可以作为节点或关系的属性,也可用于查询条件、函数参数或返回结果。
4.1 基本数据类型
4.2 复合数据类型
第 5 章 Cypher函数
Cypher 提供了丰富的内置函数,用于处理字符串、数值、集合、日期时间、布尔值等类型的数据。
5.1 字符串函数
用于对字符串进行格式化、截取、替换等常见操作,便于对文本属性进行处理和筛选。
5.2 数学函数
提供基础的数学计算功能,如绝对值、四舍五入、取整、开方和生成随机数等。
5.3 集合函数
用于处理列表数据结构,支持统计长度、获取首尾元素以及判断元素是否存在等操作。
5.4 日期时间函数
用于获取当前的日期、时间或完整的时间戳,常用于记录数据创建和修改的时间点。
第 6 章 Cypher高级查询
Cypher 支持多种高级查询功能,用于增强数据筛选、排序、分页、统计、合并等能力,帮助我们更灵活地从图中提取和处理数据。本章将介绍 MATCH 语句常用的组合方式与增强用法。
6.1 数据准备
为了更好地理解 Cypher 的高级查询功能,我们需要在图数据库中预先构建一套示例数据集。该数据集围绕“人物-电影”构建图模型,模拟了导演、演员、电影之间的真实关系,并引入社交网络中的“关注”关系。数据模型如下图所示:
MATCH (n) DETACH DELETE n;
CREATE
(:Person {name:'张艺谋', birth:'1951-11-14'}),
(:Person {name:'陈凯歌', birth:'1952-08-12'}),
(:Person {name:'巩俐', birth:'1965-12-31'}),
(:Person {name:'葛优', birth:'1957-04-19'}),
(:Person {name:'章子怡', birth:'1979-02-09'}),
(:Person {name:'刘德华', birth:'1961-09-27'}),
(:Person {name:'吴京', birth:'1974-04-03'}),
(:Person {name:'贾玲', birth:'1982-04-29'}),
(:Person {name:'郭帆', birth:'1980-12-15'});
CREATE
(:Movie {title:'红高粱', year:1987, rating:8.4, genre:['文艺','历史']}),
(:Movie {title:'活着', year:1994, rating:9.2, genre:['剧情','历史']}),
(:Movie {title:'霸王别姬', year:1993, rating:9.6, genre:['剧情','爱情']}),
(:Movie {title:'英雄', year:2002, rating:7.5, genre:['动作','武侠']}),
(:Movie {title:'无间道', year:2002, rating:9.1, genre:['犯罪','悬疑']}),
(:Movie {title:'一代宗师', year:2013, rating:8.0, genre:['动作','传记']}),
(:Movie {title:'流浪地球', year:2019, rating:8.5, genre:['科幻','灾难']}),
(:Movie {title:'战狼2', year:2017, rating:7.1, genre:['动作','军事']}),
(:Movie {title:'你好,李焕英', year:2021, rating:7.7, genre:['喜剧','家庭']}),
(:Movie {title:'满江红', year:2023, rating:7.2, genre:['悬疑','历史']});
MATCH
(zhang:Person {name:'张艺谋'}),
(chen:Person {name:'陈凯歌'}),
(liu:Person {name:'刘德华'}),
(wu:Person {name:'吴京'}),
(jia:Person {name:'贾玲'}),
(guo:Person {name:'郭帆'}),
(m1:Movie {title:'红高粱'}),
(m2:Movie {title:'活着'}),
(m3:Movie {title:'霸王别姬'}),
(m4:Movie {title:'英雄'}),
(m5:Movie {title:'无间道'}),
(m6:Movie {title:'战狼2'}),
(m7:Movie {title:'你好,李焕英'}),
(m8:Movie {title:'流浪地球'}),
(m9:Movie {title:'满江红'})
CREATE
(zhang)-[:DIRECTED {award:true}]->(m1),
(zhang)-[:DIRECTED {award:true}]->(m2),
(zhang)-[:DIRECTED {award:false}]->(m4),
(zhang)-[:DIRECTED {award:false}]->(m9),
(chen)-[:DIRECTED {award:true}]->(m3),
(liu)-[:DIRECTED {award:false}]->(m5),
(wu)-[:DIRECTED {award:false}]->(m6),
(jia)-[:DIRECTED {award:true}]->(m7),
(guo)-[:DIRECTED {award:true}]->(m8);
MATCH
(gong:Person {name:'巩俐'}), (ge:Person {name:'葛优'}),
(zhangyi:Person {name:'章子怡'}), (liu:Person {name:'刘德华'}),
(wu:Person {name:'吴京'}), (zhang:Person {name:'张艺谋'}),
(jia:Person {name:'贾玲'}),
(m1:Movie {title:'红高粱'}), (m2:Movie {title:'活着'}),
(m3:Movie {title:'霸王别姬'}), (m4:Movie {title:'英雄'}),
(m5:Movie {title:'无间道'}), (m6:Movie {title:'流浪地球'}),
(m7:Movie {title:'满江红'}), (m8:Movie {title:'战狼2'}),
(m9:Movie {title:'你好,李焕英'})
CREATE
(gong)-[:ACTED_IN {role:'九儿', award:true}]->(m1),
(gong)-[:ACTED_IN {role:'家珍', award:false}]->(m2),
(ge)-[:ACTED_IN {role:'福贵', award:true}]->(m2),
(ge)-[:ACTED_IN {role:'袁四爷', award:false}]->(m3),
(zhangyi)-[:ACTED_IN {role:'如月', award:false}]->(m4),
(zhangyi)-[:ACTED_IN {role:'宫二', award:true}]->(m7),
(liu)-[:ACTED_IN {role:'刘建明', award:false}]->(m5),
(wu)-[:ACTED_IN {role:'刘培强', award:true}]->(m6),
(zhang)-[:ACTED_IN {role:'秦桧', award:false}]->(m7),
(wu)-[:ACTED_IN {role:'冷锋', award:true}]->(m8),
(jia)-[:ACTED_IN {role:'贾晓玲', award:true}]->(m9);
MATCH
(gong:Person {name:'巩俐'}), (zhang:Person {name:'张艺谋'}),
(zhangyi:Person {name:'章子怡'}), (chen:Person {name:'陈凯歌'}),
(ge:Person {name:'葛优'}), (liu:Person {name:'刘德华'}),
(wu:Person {name:'吴京'}), (jia:Person {name:'贾玲'}),
(guo:Person {name:'郭帆'})
CREATE
(gong)-[:FOLLOWS]->(zhang),
(zhangyi)-[:FOLLOWS]->(zhang),
(zhang)-[:FOLLOWS]->(chen),
(ge)-[:FOLLOWS]->(chen),
(liu)-[:FOLLOWS]->(zhang),
(gong)-[:FOLLOWS]->(zhangyi),
(wu)-[:FOLLOWS]->(zhang),
(jia)-[:FOLLOWS]->(zhang),
(guo)-[:FOLLOWS]->(zhang),
(liu)-[:FOLLOWS]->(wu),
(zhang)-[:FOLLOWS]->(guo);
|

6.2 过滤
在图查询中,我们不仅要匹配( MATCH )图结构(节点和关系),还需要筛选符合特定条件的数据。 Cypher 使用 WHERE 子句来实现数据过滤功能,它可以应用于节点、关系的属性,支持函数、布尔逻辑、列表判断等多种表达式。
6.2.1 基本比较运算符
WHERE 子句支持多种比较运算符,如 =, <>, <, >, <=, >= 。
示例:查询出生在 1970 年之后的演员
MATCH (p:Person) WHERE p.birth > '1970-01-01' RETURN p.name, p.birth
|
6.2.2 多条件组合
可以通过 AND 和 OR 组合多个判断条件,构建复杂的过滤逻辑 。
示例:查询评分高于 8 且年份早于 2000 年的电影
MATCH (m:Movie) WHERE m.rating > 8.0 AND m.year < 2000 RETURN m.title, m.year, m.rating
|
6.2.3 集合包含
IN 操作用于判断某个值是否包含在一个列表中。
示例:查找类型包含 “ 历史 ” 的电影
MATCH (m:Movie) WHERE '历史' IN m.genre RETURN m.title, m.genre
|
6.2.4 字符串匹配
可使用 CONTAINS 、 STARTS WITH 、 END_WITH 操作进行字符串匹配, 适用于文本类型的属性,支持模糊或前缀匹配。
示例:查询名字中包含 “张”的人物
MATCH (p:Person) WHERE p.name CONTAINS '张' RETURN p.name
|
6.2.5 空值判断
可使用 IS NULL / IS NOT NULL 进行空值判断, 用于判断属性是否存在或为空,特别适用于数据完整性筛选。
MATCH (p:Person) WHERE p.birth IS NULL RETURN p.name
|
6.3 排序
在图查询中,当我们需要对结果集按某种规则进行升序或降序排列时,可以使用 Cypher 的 ORDER BY 子句。它类似于 SQL 中的排序功能,常与 RETURN 一起使用,适用于数值、字符串、日期等属性字段。
ORDER BY 字句 默认使用 升序 ( ASC ),也可以显式指定为 DESC (降序)。
示例:按电影评分从高到低排序
MATCH (m:Movie) RETURN m.title, m.rating ORDER BY m.rating DESC
|
6.4 分页
在实际应用中,返回的数据量往往较大,不适合一次性展示或处理。为此, Cypher 提供了 SKIP 和 LIMIT 子句,用于对查询结果进行分页控制,非常适用于构建分页查询接口或分批处理数据。
6.4.1 使用 LIMIT 限制返回数量
LIMIT n 表示最多返回前 n 条结果,用于快速查看或测试数据 。
示例:返回评分最高的前 3 部电影
MATCH (m:Movie) RETURN m.title, m.rating ORDER BY m.rating DESC LIMIT 3
|
6.4.2 使用 SKIP 跳过指定数量
SKIP n 表示跳过前 n 条记录,通常与 LIMIT 搭配实现分页功能。
示例:跳过前 5 条,返回第 6~10 条电影
MATCH (m:Movie) RETURN m.title, m.year ORDER BY m.year DESC SKIP 5 LIMIT 5
|
6.5 聚合
Cypher 提供了多种聚合函数,用于对图数据进行计数、求平均、求最大最小值、聚合列表等统计分析。当 RETURN 中同时包含聚合函数和非聚合字段时, Cypher 会 自动按照非聚合字段进行分组 ,无需显式使用 SQL 中的 GROUP BY 关键字。
6.5.1 数值类聚合
这类函数用于对数值属性进行处理,支持统计数量 count() 、平均值 avg() 、总和 sum() 、最大值 max() 和最小值 min() 等操作。
示例:统计演员总数(去重)
MATCH (p:Person)-[:ACTED_IN]->() RETURN count(DISTINCT p) AS 演员人数
|
示例:每位演员参演电影数量
MATCH (p:Person)-[:ACTED_IN]->(m:Movie) RETURN p.name, count(m) AS 参演电影数
|
6.5.2 列表类聚合
collect() 函数可以将多个结果合并为一个列表,常用于归集某一实体关联的多个对象或属性值。
示例:每位导演的作品名称列表
MATCH (p:Person)-[:DIRECTED]->(m:Movie) RETURN p.name, collect(m.title) AS 导演作品
|
6.6 联合查询
在图查询中,我们有时需要将多个字段类型相同的查询结果合并为一个统一结果集。 Cypher 提供了 UNION 和 UNION ALL 语句来实现这一功能,类似于 SQL 中的联合查询。
UNION :合并结果并自动去重
UNION ALL :合并结果但保留重复项
使用 UNION 和 UNION ALL 时,各个查询的 RETURN 字段数量和类型必须保持一致。
示例: 查询 “张艺谋” 导演和参演的电影
MATCH (p:Person {name:'张艺谋'})-[:DIRECTED]->(m:Movie)
RETURN m.title AS title, '导演' AS role
UNION
MATCH (p:Person {name:'张艺谋'})-[:ACTED_IN]->(m:Movie)
RETURN m.title AS title, '演员' AS role
|
6.7 子查询
Cypher 中的子查询使用 CALL ( 变量 ) {} 定义,用于执行独立的匹配、过滤或聚合操作。子查询对每一行输入数据执行一次,其返回的变量可在主查询中继续使用。
示例:每位导演评分最高的电影
MATCH (p:Person)-[:DIRECTED]->()
WITH DISTINCT p
CALL (p) {
MATCH (p)-[:DIRECTED]->(m:Movie)
RETURN m.title AS title, m.rating AS rating
ORDER BY rating DESC
LIMIT 1
}
RETURN p.name AS 导演, title AS 最高评分作品, rating AS 评分
|
说明:
在这个查询中, WITH 子句的使用起到了关键作用。它是 Cypher 中用于中间结果传递的重要语句,用法上与 RETURN 非常相似,语法格式也几乎相同。
WITH 和 RETURN 的唯一区别在于:
- WITH 将结果传递给下一阶段查询
- RETURN 则用于输出最终结果。
本示例中的 WITH DISTINCT p 表示从所有匹配到的导演中只保留唯一的 p ,从而避免重复执行子查询。
在子查询部分, CALL (p) { ... } 表示对子查询传入变量 p ,并在内部查找该导演执导的所有电影,按评分排序后选出评分最高的一部。子查询返回的 title 和 rating 会传回主查询,与导演姓名一同输出。
6.8 高级模式匹配
在 Cypher 查询中,模式匹配是核心功能之一。本节将深入学习节点、关系和路径的高级模式匹配技巧,以实现更精确和灵活的图数据查询。
6.8.1 节点模式匹配
节点的标签用于标识其类型。除了基本的单标签 (:Person) 或多标签 (:Person:Actor) 匹配, Cypher 还支持通过标签表达式组合多个标签,以表达更复杂的类型筛选条件。
标签表达式支持以下逻辑运算符:
- & 表示同时具备多个标签;
- | 表示任意一个标签匹配即可;
- ! 表示排除某个标签;
- 括号 :用于控制逻辑优先级。
示例:匹配 Person 或者 Movie 节点
MATCH (n:(Person|Movie)) RETURN n
|
示例:匹配 非 Person 节点
MATCH (n:(!Person)) RETURN n;
|
6.8.2 关系模式匹配
关系用于描述节点之间的连接类型。 除了基础的关系模式, Cypher 还支持通过 标签(类型)表达式 进行组合匹配,以及在不确定方向的情况下进行无向查询。
1) 标签(类型)表达式
示例:匹配任意一个类型的关系
MATCH (:Person {name: '张艺谋'})-[:ACTED_IN|DIRECTED]->(m:Movie)
RETURN DISTINCT m.title
|
说明:由于一个关系只能有一个类型,因此对于关系而言,表达式中的 & 操作无意义。
2) 无方向关系
默认情况下,关系匹配是有方向的(例如 → 或 ←)。在某些场景中,关系的方向可能不重要,此时可使用无方向关系模式:
示例:查询与巩俐有过合作的人
MATCH path = (p1:Person {name: '巩俐'})-[:ACTED_IN]-(m:Movie)-[:ACTED_IN]-(p2:Person)
RETURN path;
|
6.8.3 路径模式匹配
在图数据库中,路径用于描述节点之间通过若干关系连接而成的结构。 Cypher 提供了强大的路径模式语法,支持指定路径长度范围 ,可 用于匹配 固定长度 或 变长 路径 。
语法形式如下:
()-[:TYPE]->{n}()
()-[:TYPE]->{m,n}()
()-[:TYPE]->{m,}()
()-[:TYPE]->{,n}()
|
示例 :查询张艺谋粉丝的粉丝
MATCH path= (a:Person)-[:FOLLOWS]->{2}(b:Person{name:'张艺谋'})
RETURN path
|
第 7 章 约束
7.1 概述
在图数据库中,为了保持数据的一致性和完整性,我们可以为图中的节点或关系设置约束条件( Constraint )。 Neo4j 支持如下几种约束:
- 属性唯一性约束
- 属性存在约束(社区版不支持)
- 属性类型约束(社区版不支持)
- 键约束(社区版不支持)
7.2 属性唯一约束
7.2.1 概述
Neo4j 中的唯一性约束用于确保某个或某组属性在具有特定标签的所有节点,或具有特定类型的所有关系中具有唯一值。该机制防止重复数据的写入,增强图数据的一致性。
原则说明:
Ø 唯一性约束可应用于节点或关系。
Ø 如果是多个属性的组合约束,要求这些属性值的组合在图中是唯一的。
Ø 当尝试插入违反唯一性的节点或关系时,将抛出错误,阻止写入。
7.2.2 语法
7.2.2.1 创建约束
1) 节点单属性
要求所有具有特定标签的节点在指定属性上唯一。语法如下
CREATE CONSTRAINT constraint_name
FOR (n:Label)
REQUIRE n.property IS UNIQUE;
|
2) 关系单属性
要求所有特定类型的关系在指定属性上唯一。 语法如下
CREATE CONSTRAINT constraint_name
FOR ()-[r:REL_TYPE]-()
REQUIRE r.property IS UNIQUE;
|
3) 节点 复合属性
要求所有具有特定标签的节点在指定多个属性上唯一。语法如下
CREATE CONSTRAINT constraint_name
FOR (n:Label)
REQUIRE (n.prop1, n.prop2) IS UNIQUE;
|
4) 关系 复合属性
CREATE CONSTRAINT constraint_name
FOR ()-[r:REL_TYPE]-()
REQUIRE (r.prop1, r.prop2) IS UNIQUE;
|
7.2.2.2 查看约束
7.2.2.3 删除约束
DROP CONSTRAINT constraint_name;
|
7.2.3 案例
设计一个 User 节点,其 userId 属性必须唯一。防止系统中出现重复用户标识。
1) 定义唯一性约束
CREATE CONSTRAINT unique_user_id
FOR (u:User)
REQUIRE u.userId IS UNIQUE;
|
2) 正常插入用户节点
插入两个具有不同 userId 的用户:
CREATE (u1:User {userId: 'u001', name: 'Alice', email: 'alice@example.com'});
CREATE (u2:User {userId: 'u002', name: 'Bob', email: 'bob@example.com'});
|
成功插入,未触发约束。
3) 尝试插入重复 userId
CREATE (u3:User {userId: 'u001', name: 'Charlie', email: 'charlie@example.com'});
|
执行后, Neo4j 返回错误:
Neo.ClientError.Schema.ConstraintValidationFailed
Node(124) already exists with label `User` and property `userId` = 'u001'
|
4) 查看约束
返回结果如下
5) 删除约束
DROP CONSTRAINT unique_user_id;
|
第 8 章 使用Python访问Neo4j
🎯 官方教程 : https://neo4j.ac.cn/docs/python-manual/current/
8.1 安装neo4j驱动
Neo4j Python 驱动程序是通过 Python 应用程序与 Neo4j 实例交互的官方库。安装命令如下:
8.2 创建Driver对象
连接 Neo4j 的第一步是创建 Driver 对象,它负责管理数据库连接池,是与数据库交互的核心入口。 Driver 是不可变的、线程安全的,但创建成本较高,因此在应用中应仅创建一个实例并复用,避免重复创建带来的性能开销。使用完毕后必须关闭 Driver 以释放资源,可以通过显式调用 driver.close() 方法,或使用 with 语句自动管理其生命周期,推荐后者以避免资源泄漏。
示例代码如下:
from neo4j import GraphDatabase
URI = "neo4j://localhost"
AUTH = ("neo4j", "password")
with GraphDatabase.driver(URI, auth=AUTH) as driver:
driver.verify_connectivity()
print("Connection established.")
|
8.3 执行Cypher语句
execute_query() 是 Neo4j Python 驱动提供的简洁高效的查询执行方法,适合大多数基础查询场景。
方法签名(只包含常用参数,完整签名可参考 官方文档 )如下:
execute_query(
query: str,
parameters_: dict = None,
database_: str = None,
**kwargs
) -> EagerResult
|
参数说明:
返回值:
execute_query() 默认返回一个 EagerResult ,是一个命名元组, 包含以下组件:
具体案例如下:
from neo4j import GraphDatabase
URI = "neo4j://localhost:7687"
AUTH = ("neo4j", "Atguigu.123")
with GraphDatabase.driver(URI, auth=AUTH) as driver:
records, summary, keys = driver.execute_query(
"""
MATCH (p:Person{name:$name})-[r:DIRECTED]->(m:Movie)
WHERE m.year > $year
RETURN p.name AS director,m.year AS year, m.title AS movie
""",
parameters_={"name": "张艺谋", "year": 1990},
database_="neo4j"
)
print(f"查询返回了 {len(records)} 条记录")
for record in records:
print(f"{record['director']}在{record['year']}年拍摄了《{record['movie']}》")
|
第 9 章 Neo4j 的 ORM 与客户端库
🎯 在应用开发中,通过编程语言与 Neo4j 交互时,除了直接使用 Cypher 查询,还可以利用各种客户端库或 ORM(对象关系映射)框架 。这些工具能够简化代码编写,提高开发效率。以下分别介绍在 Java 和 Python 生态中的主流选择 。
9.1 Java 生态
Java 开发者主要有两种主流选择,一种是与 Spring 生态深度整合的框架,另一种是 官方 提供的底层驱动 。
关键介绍:
- 首选推荐 :对于大多数现代 Java 应用,特别是基于 Spring Boot 的项目, Spring Data Neo4j 是最佳选择。它极大地简化了数据访问层的开发。
- 核心概念 :在 ORM 中,使用 @NodeEntity 注解定义实体类,使用 @Relationship 注解定义关系。通过继承 Neo4jRepository 接口,可以直接获得常用的 CRUD 方法
- 原生控制 :当需要执行复杂 Cypher 查询或对 性能 有极致要求时,可以直接使用 Neo4j Java Driver ,它在提供强大控制力的同时保证了效率。
9.2 Python 生态
Python 生态提供了从官方驱动到高级工具包等多种选择 。
关键介绍:
- 重要提示 :在选择 py2neo 时需注意,有资料指出其某个历史版本 可能不支持 Neo4j 5.x 及以上版本 。在选择前,请务必查阅其官方文档以确认与你当前使用的 Neo4j 数据库版本的兼容性
- 灵活性与性能 : py2neo 在提供便利性和功能丰富性上表现突出。而 Neo4j Python Driver 则在性能和底层控制上更胜一筹,是许多高性能应用的基础。
- 开发体验 :如果你希望像操作 Django 模型一样来操作图数据, neomodel 会提供非常熟悉和舒适的开发体验。
9.3 如何选择
- 项目架构 :若为 Spring Boot 项目, Spring Data Neo4j 是自然之选。对于 Python 中小型项目或脚本, py2neo 和 neomodel 都能提供很好的开发效率。
- 团队熟悉度 :团队若熟悉 Spring 生态或 Django ORM,可选择对应的框架以降低学习成本。若对 Cypher 很熟悉,直接使用官方驱动也很高效。
- 性能与控制 :对性能有极致要求,或需要进行深度优化时,两个语言的官方驱动都是最可靠的选择。
- 数据模型复杂度 :对于结构固定、模型规范的项目,使用 ORM 优势明显。对于模型灵活、变化频繁的图结构,直接使用 Cypher 配合官方驱动可能更灵活。
|