Cypher 基础
Cypher 是 Neo4j 的声明式查询语言,专为图数据操作而设计。它的语法直观易懂,类似于自然语言,让复杂的关系查询变得简单。
Cypher 概述
Cypher 使用 ASCII 艺术风格的模式来表示图结构:
()表示节点-->表示有向关系[]表示关系的详细信息
-- 查询模式:张三的朋友
MATCH (zhangsan:Person {name: '张三'})-[:FRIEND]->(friend)
RETURN friend
创建数据(CREATE)
创建节点
-- 创建单个节点
CREATE (p:Person {name: '张三', age: 30})
-- 创建多个节点
CREATE (a:Person {name: '李四', age: 28})
CREATE (b:Person {name: '王五', age: 32})
-- 创建带有多个标签的节点
CREATE (n:Person:Employee {name: '赵六', department: '技术部'})
创建关系
-- 创建节点并建立关系
CREATE (zhangsan:Person {name: '张三'})-[:FRIEND {since: '2020-01-01'}]->(lisi:Person {name: '李四'})
-- 为已存在的节点创建关系
MATCH (a:Person {name: '张三'}), (b:Person {name: '王五'})
CREATE (a)-[:COLLEAGUE {department: '技术部'}]->(b)
MERGE 语句
MERGE 会检查数据是否存在,不存在则创建,存在则返回已有数据:
-- 如果节点不存在则创建
MERGE (p:Person {name: '张三'})
ON CREATE SET p.created = datetime()
ON MATCH SET p.lastSeen = datetime()
RETURN p
-- 确保关系存在
MATCH (a:Person {name: '张三'}), (b:Person {name: '李四'})
MERGE (a)-[r:FRIEND]->(b)
ON CREATE SET r.since = date()
RETURN r
查询数据(MATCH)
基本查询
-- 查询所有节点
MATCH (n)
RETURN n
-- 查询特定标签的节点
MATCH (p:Person)
RETURN p
-- 查询带有特定属性的节点
MATCH (p:Person {name: '张三'})
RETURN p
-- 查询特定属性(使用 WHERE)
MATCH (p:Person)
WHERE p.age > 25
RETURN p.name, p.age
查询关系
-- 查询所有关系
MATCH ()-[r]->()
RETURN r
-- 查询特定类型的关系
MATCH ()-[r:FRIEND]->()
RETURN r
-- 查询节点的关系
MATCH (p:Person {name: '张三'})-[r]->(other)
RETURN type(r), other.name
-- 查询双向关系(不指定方向)
MATCH (p:Person {name: '张三'})-[r]-(other)
RETURN type(r), other.name
多跳查询
-- 查询朋友的朋友(2跳)
MATCH (p:Person {name: '张三'})-[:FRIEND]->()-[:FRIEND]->(fof)
RETURN fof.name
-- 查询可变深度的关系
MATCH (p:Person {name: '张三'})-[:FRIEND*2..4]->(fof)
RETURN fof.name
-- 查询最短路径
MATCH path = shortestPath(
(a:Person {name: '张三'})-[:FRIEND*]-(b:Person {name: '王五'})
)
RETURN path
更新数据(SET)
更新属性
-- 更新单个属性
MATCH (p:Person {name: '张三'})
SET p.age = 31
RETURN p
-- 更新多个属性
MATCH (p:Person {name: '张三'})
SET p.age = 31, p.city = '上海'
RETURN p
-- 添加新属性
MATCH (p:Person {name: '张三'})
SET p.email = '[email protected]'
RETURN p
删除属性
-- 删除单个属性
MATCH (p:Person {name: '张三'})
REMOVE p.email
RETURN p
-- 删除多个属性
MATCH (p:Person {name: '张三'})
REMOVE p.age, p.city
RETURN p
添加/删除标签
-- 添加标签
MATCH (p:Person {name: '张三'})
SET p:Employee:Manager
RETURN p
-- 删除标签
MATCH (p:Person {name: '张三'})
REMOVE p:Manager
RETURN p
删除数据(DELETE)
-- 删除关系
MATCH ()-[r:FRIEND]->()
WHERE r.since < date('2020-01-01')
DELETE r
-- 删除节点(必须先删除关系)
MATCH (p:Person {name: '张三'})-[r]-()
DELETE r
WITH p
DELETE p
-- 级联删除(删除节点及其所有关系)
MATCH (p:Person {name: '张三'})
DETACH DELETE p
条件过滤(WHERE)
-- 比较运算符
MATCH (p:Person)
WHERE p.age > 25 AND p.age < 35
RETURN p.name
-- 字符串匹配
MATCH (p:Person)
WHERE p.name STARTS WITH '张'
RETURN p.name
MATCH (p:Person)
WHERE p.name CONTAINS '三'
RETURN p.name
-- 正则表达式
MATCH (p:Person)
WHERE p.name =~ '张.*'
RETURN p.name
-- IN 运算符
MATCH (p:Person)
WHERE p.name IN ['张三', '李四', '王五']
RETURN p.name
-- 检查属性是否存在
MATCH (p:Person)
WHERE p.email IS NOT NULL
RETURN p.name
-- 检查列表
MATCH (p:Person)
WHERE '技术部' IN p.departments
RETURN p.name
结果处理
排序(ORDER BY)
-- 升序排序
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age
-- 降序排序
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age DESC
-- 多字段排序
MATCH (p:Person)
RETURN p.name, p.age, p.city
ORDER BY p.city, p.age DESC
分页(SKIP / LIMIT)
-- 限制返回数量
MATCH (p:Person)
RETURN p.name
LIMIT 10
-- 跳过前 N 条
MATCH (p:Person)
RETURN p.name
SKIP 10
LIMIT 10
-- 分页查询(第 3 页,每页 10 条)
MATCH (p:Person)
RETURN p.name
ORDER BY p.name
SKIP 20
LIMIT 10
去重(DISTINCT)
-- 去除重复结果
MATCH (p:Person)-[:FRIEND]->(friend)
RETURN DISTINCT friend.city
综合示例
社交网络场景
-- 创建示例数据
CREATE (zhangsan:Person {name: '张三', age: 30, city: '北京'})
CREATE (lisi:Person {name: '李四', age: 28, city: '上海'})
CREATE (wangwu:Person {name: '王五', age: 32, city: '北京'})
CREATE (zhaoliu:Person {name: '赵六', age: 25, city: '广州'})
CREATE (zhangsan)-[:FRIEND {since: date('2020-01-15')}]->(lisi)
CREATE (lisi)-[:FRIEND {since: date('2019-06-20')}]->(wangwu)
CREATE (wangwu)-[:FRIEND {since: date('2021-03-10')}]->(zhaoliu)
CREATE (zhangsan)-[:COLLEAGUE]->(wangwu)
-- 查询张三的所有朋友
MATCH (zhangsan:Person {name: '张三'})-[:FRIEND]-(friend)
RETURN friend.name, friend.age
-- 查询张三的朋友的朋友(推荐好友)
MATCH (zhangsan:Person {name: '张三'})-[:FRIEND]->()-[:FRIEND]->(potential)
WHERE NOT (zhangsan)-[:FRIEND]-(potential)
RETURN potential.name, potential.city
-- 统计每个城市的人数
MATCH (p:Person)
RETURN p.city, count(p) AS count
ORDER BY count DESC
-- 查询最年轻的朋友
MATCH (zhangsan:Person {name: '张三'})-[:FRIEND]-(friend)
RETURN friend.name, friend.age
ORDER BY friend.age
LIMIT 1
最佳实践
-
使用参数化查询:避免 SQL 注入,提高性能
MATCH (p:Person {name: $name})
RETURN p -
合理使用索引:为经常查询的属性创建索引
CREATE INDEX person_name FOR (p:Person) ON (p.name) -
限制返回数量:避免查询大量数据
MATCH (p:Person)
RETURN p
LIMIT 100 -
使用 EXPLAIN 分析查询:了解查询执行计划
EXPLAIN MATCH (p:Person {name: '张三'})-[:FRIEND*5]->()
RETURN p
下一步
掌握了基础 CRUD 操作后,继续学习 高级查询,了解聚合函数、路径查找等高级功能。