docker安装 1 mkdir -p ~/neo4j/{data,logs,plugins,conf}
在~/neo4j目录下创建docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 version: '3.8' services: neo4j: image: neo4j:latest container_name: neo4j restart: always ports: - "7474:7474" - "7687:7687" - "7473:7473" environment: - NEO4J_AUTH=neo4j/123456 - NEO4J_server_memory_heap_initial__size=512m - NEO4J_server_memory_heap_max__size=2G - NEO4J_server_memory_pagecache_size=1G volumes: - ~/neo4j/data:/data - ~/neo4j/logs:/logs - ~/neo4j/plugins:/plugins - ~/neo4j/conf:/conf deploy: resources: limits: cpus: '1' memory: 4G
访问 http://127.0.0.1:7474
输入刚刚配置的用户名密码。
以例子来学习命令 例子概述 以学生、课程、老师为节点;选课、授课、任教为关系。
1. 节点类型(Label)& 属性
Student(学生) :id (学号)、name (姓名)、age (年龄)、gender (性别)
Course(课程) :id (课程号)、name (课程名)、credit (学分)、type (课程类型:必修 / 选修)
Teacher(老师) :id (工号)、name (姓名)、subject (授课科目)、age (年龄)
2. 关系类型(Relationship)& 属性
STUDY(选课) :Student → Course,属性:score (成绩)、semester (学期)
TEACH(授课) :Teacher → Course,属性:teach_year (授课年份)
WORK_AT(任教) :Teacher → (可选,无属性,指向学校,简化为固定值)
命令 一、基础操作:创建节点(CREATE / MERGE) 创建节点是图数据库的基础,推荐MERGE (不存在则创建,存在则匹配,避免重复),新手也可先学CREATE (直接创建,会重复)。
1. 单节点创建(CREATE) 1 2 3 4 5 6 7 8 9 10 11 // 创建1个学生节点 CREATE (s:Student {id: 202401, name: "张三", age: 20, gender: "男"}) RETURN s; // RETURN 用于返回创建的节点,可省略 // 创建1个课程节点 CREATE (c:Course {id: "C001", name: "Python基础", credit: 3, type: "必修"}) RETURN c; // 创建1个老师节点 CREATE (t:Teacher {id: "T001", name: "李老师", subject: "计算机", age: 35}) RETURN t;
2.批量创建节点(CREATE 多个) 1 2 3 4 5 6 7 8 9 // 批量创建2个学生、2个课程、2个老师 CREATE (s2:Student {id: 202402, name: "李四", age: 19, gender: "女"}), (s3:Student {id: 202403, name: "王五", age: 20, gender: "男"}), (c2:Course {id: "C002", name: "图数据库", credit: 2, type: "选修"}), (c3:Course {id: "C003", name: "Java开发", credit: 3, type: "必修"}), (t2:Teacher {id: "T002", name: "王老师", subject: "数学", age: 40}), (t3:Teacher {id: "T003", name: "张老师", subject: "计算机", age: 32}) RETURN s2, s3, c2, c3, t2, t3;
3.防重复创建(MERGE 推荐) 1 2 3 4 // 若学号202401的学生不存在则创建,存在则直接匹配 MERGE (s:Student {id: 202401}) ON CREATE SET s.name = "张三", s.age = 20, s.gender = "男" RETURN s;
ON CREATE SET :仅在节点创建时设置属性,避免覆盖已有数据。
二、核心操作:创建节点间的关系(CREATE / MERGE) 关系是图数据库的灵魂,格式为 (节点1)-[关系名:关系类型 {属性}]->(节点2),箭头表示关系方向。
1. 先匹配节点,再创建关系(推荐,避免创建无效关系) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 1. 张三(202401)选了Python基础(C001),成绩90,2024秋学期 MATCH (s:Student {id: 202401}), (c:Course {id: "C001"}) CREATE (s)-[r:STUDY {score: 90, semester: "2024秋"}]->(c) RETURN s, r, c; // 2. 李老师(T001)讲授Python基础(C001),2024年授课 MATCH (t:Teacher {id: "T001"}), (c:Course {id: "C001"}) CREATE (t)-[r:TEACH {teach_year: 2024}]->(c) RETURN t, r, c; // 3. 批量创建关系(李四/王五选课,张老师授课) MATCH (s2:Student {id: 202402}), (s3:Student {id: 202403}), (c1:Course {id: "C001"}), (c2:Course {id: "C002"}), (t3:Teacher {id: "T003"}) CREATE (s2)-[:STUDY {score: 85, semester: "2024秋"}]->(c1), (s2)-[:STUDY {score: 92, semester: "2024秋"}]->(c2), (s3)-[:STUDY {score: 78, semester: "2024秋"}]->(c1), (t3)-[:TEACH {teach_year: 2024}]->(c2), (t3)-[:TEACH {teach_year: 2024}]->(c3), (t1:Teacher {id: "T001"})-[:WORK_AT]->({name: "XX大学"}) // 直接创建带关系的匿名节点(学校) RETURN *; // RETURN * 返回所有匹配/创建的节点和关系
2.防重复关系(MERGE 关系) 1 2 3 4 5 // 避免张三重复创建选C001的关系 MATCH (s:Student {id: 202401}), (c:Course {id: "C001"}) MERGE (s)-[r:STUDY {semester: "2024秋"}]->(c) ON CREATE SET r.score = 90 // 仅创建时设成绩 RETURN s, r, c;
三、查询操作:MATCH (最常用,覆盖单节点 / 关系 / 多条件 / 聚合) 查询是 Cypher 的核心,MATCH 用于匹配节点 / 关系,搭配WHERE筛选、RETURN返回、ORDER BY排序、LIMIT限制结果,新手重点掌握。
1. 简单查询:匹配所有 / 指定类型节点 1 2 3 4 5 6 7 8 9 10 // 1. 查询所有节点(新手调试用,生产环境避免) MATCH (n) RETURN n LIMIT 10; // LIMIT 限制返回10个,防止数据过多 // 2. 查询所有学生节点,返回姓名和年龄(指定属性,更简洁) MATCH (s:Student) RETURN s.name, s.age; // 3. 查询所有必修课程,按学分降序 MATCH (c:Course {type: "必修"}) RETURN c.name, c.credit ORDER BY c.credit DESC;
2.带关系的查询:匹配节点 + 关系(核心) 1 2 3 4 5 6 7 8 9 10 11 12 13 // 1. 查询张三选了哪些课程,返回课程名和成绩 MATCH (s:Student {name: "张三"})-[r:STUDY]->(c:Course) RETURN s.name, c.name, r.score; // 2. 查询谁教了Python基础(反向查询,箭头可省略) MATCH (t:Teacher)-[r:TEACH]->(c:Course {name: "Python基础"}) RETURN t.name, r.teach_year; // 3. 查询选了Python基础的所有学生姓名和成绩,按成绩升序 MATCH (s:Student)-[r:STUDY]->(c:Course {name: "Python基础"}) RETURN s.name, r.score ORDER BY r.score ASC LIMIT 5;
3.多条件筛选:WHERE 子句(复杂条件用,比直接写属性更灵活) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 1. 查询年龄≥20的男学生,选了学分≥3的课程 MATCH (s:Student)-[r:STUDY]->(c:Course) WHERE s.age >= 20 AND s.gender = "男" AND c.credit >=3 RETURN s.name, c.name, r.score; // 2. 查询成绩在80~90之间的选课记录 MATCH (s:Student)-[r:STUDY]->(c:Course) WHERE r.score >= 80 AND r.score <= 90 RETURN s.name, c.name, r.score // 3. 模糊查询:课程名包含「数据库」的课程 MATCH (c:Course) WHERE c.name CONTAINS "数据库" // 还可用 STARTS WITH(以...开头)/ ENDS WITH(以...结尾) RETURN c.name, c.type;
4.聚合查询:COUNT/SUM/AVG/MIN/MAX(统计分析用) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 1. 统计学生总数、课程总数 MATCH (s:Student) RETURN COUNT(s) AS student_count; MATCH (c:Course) RETURN COUNT(c) AS course_count; // 2. 计算Python基础的平均成绩、最高/最低成绩 MATCH (s)-[r:STUDY]->(c:Course {name: "Python基础"}) RETURN AVG(r.score) AS avg_score, MAX(r.score) AS max_score, MIN(r.score) AS min_score, COUNT(s) AS study_count; // 选课人数 // 3. 统计每个学生的选课门数和总成绩,按选课门数降序 MATCH (s:Student)-[r:STUDY]->(c:Course) WITH s, COUNT(c) AS course_num, SUM(r.score) AS total_score // WITH 临时传递结果 RETURN s.name, course_num, total_score ORDER BY course_num DESC;
5.多跳关系查询:路径查询(查间接关联,如「学生→课程→老师」) 1 2 3 4 5 6 7 8 9 10 11 12 // 1. 查询张三的所有授课老师(学生→课程→老师,2跳关系) MATCH (s:Student {name: "张三"})-[r1:STUDY]->(c:Course)<-[r2:TEACH]-(t:Teacher) RETURN s.name, c.name, t.name; // 2. 通用路径查询:匹配张三和所有老师的最短路径(*表示任意跳数,1..3表示1-3跳) MATCH p=shortestPath((s:Student {name: "张三"})-[*]-(t:Teacher)) RETURN p; // 3. 查询教过选修课程的老师,且老师年龄<40 MATCH (t:Teacher)-[r:TEACH]->(c:Course {type: "选修"}) WHERE t.age < 40 RETURN DISTINCT t.name; // DISTINCT 去重,避免老师教多门选修课重复显示
四、修改操作:SET (修改节点 / 关系的属性,新增 / 更新) SET 可新增属性 (节点 / 关系无该属性时)或更新属性 (已有该属性时),搭配MATCH定位要修改的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 1. 修改节点属性:张三年龄加1,新增「专业」属性 MATCH (s:Student {name: "张三"}) SET s.age = s.age + 1, s.major = "计算机科学与技术" RETURN s; // 2. 修改关系属性:张三的Python基础成绩改为95 MATCH (s:Student {name: "张三"})-[r:STUDY]->(c:Course {name: "Python基础"}) SET r.score = 95 RETURN s.name, c.name, r.score; // 3. 批量修改:所有必修课程学分加1 MATCH (c:Course {type: "必修"}) SET c.credit = c.credit + 1 RETURN c.name, c.credit;
五、删除操作:DELETE / REMOVE (别搞混!) 关键区别:
DELETE :删除节点 或关系 (删除节点前必须先删除其所有关系,否则报错)
REMOVE :删除节点 / 关系的属性 (不是删除对象本身)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // ******************** REMOVE:删除属性 ******************** // 删除张三的「专业」属性 MATCH (s:Student {name: "张三"}) REMOVE s.major RETURN s; // ******************** DELETE:删除关系 ******************** // 删除王五选Python基础的关系 MATCH (s:Student {name: "王五"})-[r:STUDY]->(c:Course {name: "Python基础"}) DELETE r RETURN s, c; // ******************** DELETE:删除节点(先删关系再删节点) ******************** // 删除课程C003(Java开发):先删其所有关系,再删节点 MATCH (c:Course {id: "C003"})-[r]-() // [r]-() 匹配该课程的所有入/出关系 DELETE r, c // 先删关系r,再删节点c RETURN "删除成功"; // ******************** 清空所有数据(谨慎!生产环境禁用) ******************** MATCH (n) DETACH DELETE n; // DETACH DELETE 自动删除节点的所有关系,再删除节点
六、索引与约束(优化查询,保证数据唯一性) 当数据量变大时,索引 能大幅提升查询速度;约束 能保证节点属性的唯一性(如学号、课程号不能重复),新手提前了解,后续实战必用。
1. 创建索引(针对常用查询的属性,如学生 id、课程名) 1 2 3 4 5 // 为Student的id属性创建索引 CREATE INDEX idx_student_id FOR (s:Student) ON (s.id); // 为Course的name属性创建索引 CREATE INDEX idx_course_name FOR (c:Course) ON (c.name);
2.创建唯一约束(保证属性值唯一,比索引更严格,重复创建会报错) 1 2 3 4 5 // 保证学生学号唯一(核心,避免重复创建同学号学生) CREATE CONSTRAINT constraint_student_id IF NOT EXISTS FOR (s:Student) REQUIRE s.id IS UNIQUE; // 保证课程号唯一 CREATE CONSTRAINT constraint_course_id IF NOT EXISTS FOR (c:Course) REQUIRE c.id IS UNIQUE;
3. 查看 / 删除索引 / 约束 1 2 3 4 5 6 7 8 // 查看所有索引和约束 SHOW INDEXES; // 删除索引(根据索引名,从SHOW INDEXES结果中查) DROP INDEX idx_course_name; // 删除约束(根据约束名) DROP CONSTRAINT constraint_student_id;