0%

cypher与sql对比

以学生选课场景为例来进行对比

背景说明
假设我们有一个高校教务系统,包含以下实体:

  • 学生(Student):有学号、姓名
  • 课程(Course):有课程编号、课程名、学分
  • 选课关系(Enroll):学生选了某门课,可能包含成绩(grade)

在关系型数据库中,这通常用三张表实现;在 Neo4j 中,则用节点和关系直接建模。


索引(Index)

索引用于加速查找起点(如按学号找学生、按课程名找课)。

SQL Cypher
CREATE INDEX idx_student_id ON students (student_id);
CREATE INDEX idx_course_name ON courses (course_name);
CREATE INDEX Student_studentId IF NOT EXISTS FOR (s:Student) ON s.studentId;
CREATE INDEX Course_courseName IF NOT EXISTS FOR (c:Course) ON c.courseName;

💡 注意:Neo4j 的索引只用于 MATCH 的起点(如 (s:Student {studentId: '2023001'})),后续遍历靠图结构,无需 JOIN。


查询示例

1. 选择并返回所有记录

SQL Cypher
SELECT * FROM students; MATCH (s:Student) RETURN s;

2. 返回特定字段、排序与分页

需求:列出学分最高的前 5 门课程。

SQL Cypher
SELECT course_name, credits FROM courses ORDER BY credits DESC LIMIT 5; MATCH (c:Course) RETURN c.courseName, c.credits ORDER BY c.credits DESC LIMIT 5;

3. 按名称查找单门课程

需求:查找课程名为 “数据库原理” 的课程信息。

SQL Cypher
SELECT course_name, credits FROM courses WHERE course_name = ‘数据库原理’; MATCH (c:Course {courseName: ‘数据库原理’}) RETURN c.courseName, c.credits;

更简洁:属性直接写在 {} 中,无需 WHERE


4. 按列表筛选课程

需求:查找 “高等数学” 和 “线性代数” 两门课的信息。

SQL Cypher
SELECT course_name, credits FROM courses WHERE course_name IN (‘高等数学’, ‘线性代数’); MATCH (c:Course) WHERE c.courseName IN [‘高等数学’, ‘线性代数’] RETURN c.courseName, c.credits;

5. 多条件筛选

需求:查找课程名以 “数据” 开头 且 学分 ≥ 3 的课程。

SQL Cypher
SELECT course_name, credits FROM courses WHERE course_name LIKE ‘数据%’ AND credits >= 3; MATCH (c:Course) WHERE c.courseName STARTS WITH ‘数据’ AND c.credits >= 3 RETURN c.courseName, c.credits;

💡 Neo4j 用 STARTS WITH / CONTAINS / ENDS WITH 替代 LIKE,更直观。


6. 连接学生与课程

需求:找出选了 “数据库原理” 的所有学生姓名。

SQL(需要多次 JOIN)
1
2
3
4
5
SELECT DISTINCT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
WHERE c.course_name = '数据库原理';
Cypher(直接走关系)
1
2
MATCH (c:Course {courseName: '数据库原理'}) <-[:ENROLL]- (s:Student)
RETURN DISTINCT s.name;

无需 JOIN!关系本身就是路径
关系类型 :ENROLL 直接表达了“学生选课”的语义。


7. 聚合:每门课的选课人数

需求:统计每门课程有多少人选,按人数降序,取前 3。

SQL Cypher
SELECT c.course_name, COUNT(e.student_id) AS studentCount FROM courses c LEFT JOIN enrollments e ON c.course_id = e.course_id GROUP BY c.course_id, c.course_name ORDER BY studentCount DESC LIMIT 3; MATCH (c:Course) OPTIONAL MATCH (c) <-[:ENROLL]- (s:Student) RETURN c.courseName, COUNT(s) AS studentCount ORDER BY studentCount DESC LIMIT 3;

💡 OPTIONAL MATCH 相当于 LEFT JOIN,确保没被选的课也显示(人数为 0)。


8. 聚合:每个学生的总学分

需求:计算学生 “张三” 已修课程的总学分。

SQL Cypher
SELECT SUM(c.credits) AS totalCredits FROM students s JOIN enrollments e ON s.student_id = e.student_id JOIN courses c ON e.course_id = c.course_id WHERE s.name = ‘张三’; MATCH (s:Student {name: ‘张三’}) -[:ENROLL]-> (c:Course) RETURN sum(c.credits) AS totalCredits;

图遍历天然支持“从学生出发,走到课程,累加学分”。


9. 列出每个学生选的课程(集合聚合)

需求:列出每位学生及其所选课程名(逗号分隔或列表形式)。

SQL Cypher
SELECT s.name, STRING_AGG(c.course_name, ‘, ‘ ORDER BY c.course_name) AS courses FROM students s JOIN enrollments e ON s.student_id = e.student_id JOIN courses c ON e.course_id = c.course_id GROUP BY s.student_id, s.name ORDER BY s.name; MATCH (s:Student) -[:ENROLL]-> (c:Course) RETURN s.name, COLLECT(c.courseName) AS courses ORDER BY s.name;

COLLECT() 自动将多行合并为列表,结果更结构化(适合 JSON 输出)。


总结对比

场景 SQL 特点 Cypher 优势
多表连接 需显式 JOIN,易错、性能差(尤其深度关联) 关系即路径,直接 MATCH (A)-[R]->(B)
聚合分组 必须写 GROUP BY 所有非聚合字段 隐式分组,简洁
返回嵌套结构 需用 STRING_AGG 或应用层处理 内置 COLLECT(),天然支持嵌套
查询可读性 逻辑隐藏在 JOIN 条件中 像画图一样写查询,语义清晰

Neo4j入门

Neo4j 图数据库将数据存储为节点、关系和属性,而不是以表格或文档形式。

  • 节点 表示图数据模型中的实体或离散对象。节点可以通过关系连接,在属性中存储数据,并按标签分类

    一个节点可以有多个标签 (:User:Customer)

    如:

    1
    2
    3
    4
    (:Person {name: "张三", age: 30})

    # Person 是 标签(Label)
    # {name: "张三", age: 30} 是 属性
  • 关系 表示图数据模型中节点之间的连接。关系将源节点连接到目标节点,在属性中存储数据,并按类型分类

    • 关系是有方向的 (A → B ≠ B → A)
    • 有类型(Type)(必须大写,如 KNOWS, BOUGHT
    • 也可以有属性
    1
    (:Person {name: "张三"})-[:FRIEND]->(:Person {name: "李四"})
  • 属性 用于在节点和关系上存储数据的键值对

对比:MySQL vs Neo4j

概念 MySQL(关系型) Neo4j(图数据库)
基本单元 表(Table)、行(Row) 节点(Node)、关系(Relationship)
连接方式 外键(JOIN) 直接存储关系(关系是一等公民)
查询语言 SQL Cypher(声明式、直观)
性能特点 JOIN 越多越慢 深度关联查询极快(O(1) 跳转)
数据模型 表格(二维) 图(网络结构)
阅读全文 »

CentOS 7 老树开新花:从零部署 Dify 全栈应用(含 Go/Rust/GCC 升级避坑)

本文档适用于在 CentOS 7 环境下使用源代码部署 Dify 应用,对应版本 1.9.2。由于系统较旧,部分依赖需手动升级或通过容器化方式解决兼容性问题。


一、安装与配置 Docker

1. 卸载旧版本 Docker(如有)

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

2. 安装必要依赖

1
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

3. 添加 Docker 官方 YUM 源

1
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

4. 安装 Docker Engine 及相关组件

1
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

5. 启动并设置开机自启

1
2
sudo systemctl start docker
sudo systemctl enable docker

6. 配置国内镜像加速器

阅读全文 »

Neo4j安装

Anaconda 虚拟环境完全指南:创建、管理与实战

Anaconda 的虚拟环境功能是解决 Python 项目依赖冲突的核心工具,尤其适合多项目并行开发(如同时维护 Python 3.6 的旧项目和 Python 3.11 的新项目)。

为什么要使用多个环境?

项目 需要的 Python 版本 需要的包
项目 A(TensorFlow 1.x) Python 3.6 tensorflow==1.15
项目 B(PyTorch 最新版) Python 3.9 torch>=2.0
项目 C(数据分析) Python 3.8 pandas, jupyter

如果不使用环境,这些依赖会冲突。使用环境可以完全隔离

环境创建:从基础到进阶

1. 基础创建:指定 Python 版本

创建环境时必须明确 Python 版本(避免默认版本不匹配),语法如下:

1
2
3
# 格式:conda create -n 环境名 python=具体版本
conda create -n data-analysis python=3.8 # 数据分析环境,Python 3.8
conda create -n tf2x python=3.7 # TensorFlow 2.x 环境,Python 3.7(适配性更高)
  • 版本选择原则:优先选择项目依赖包支持的稳定版本(如 PyTorch 2.0+ 推荐 Python 3.8-3.10)。
  • 命名规范:建议包含「项目类型 + Python 版本」(如 django32-py310),避免混淆。

2. 进阶创建:一键安装依赖包

创建环境时直接安装核心包,减少后续操作步骤:

1
2
3
# 创建环境并安装 numpy、pandas、jupyter(数据科学常用包)
conda create -n ds-py39 python=3.9 numpy pandas jupyter -y
# -y 参数:自动确认安装(无需手动输入 y)
  • 适用场景:新建项目时已知需要的核心依赖(如开发 Flask 项目时,可直接安装 flask gunicorn)。

  • 通道选择:若默认通道安装慢,可指定conda-forge通道(社区维护,包更全):

    1
    conda create -n ml-py310 python=3.10 -c conda-forge scikit-learn xgboost

环境管理

1. 环境激活:跨平台差异

不同操作系统的激活命令一致,但终端显示略有不同:

阅读全文 »