跳到主要内容

高级查询

本章介绍 Cypher 的高级功能,包括聚合函数、路径查找、条件表达式等,帮助你处理更复杂的查询场景。

聚合函数

常用聚合函数

-- COUNT:计数
MATCH (p:Person)
RETURN count(p) AS totalPeople

-- 统计不同城市的数量
MATCH (p:Person)
RETURN count(DISTINCT p.city) AS cityCount

-- SUM:求和
MATCH (p:Product)
RETURN sum(p.price) AS totalValue

-- AVG:平均值
MATCH (p:Person)
RETURN avg(p.age) AS averageAge

-- MIN/MAX:最值
MATCH (p:Person)
RETURN min(p.age) AS youngest, max(p.age) AS oldest

-- COLLECT:收集为列表
MATCH (p:Person)
RETURN collect(p.name) AS allNames

分组聚合

-- 按城市统计人数
MATCH (p:Person)
RETURN p.city, count(p) AS count
ORDER BY count DESC

-- 统计每个标签的节点数
MATCH (n)
RETURN labels(n), count(n)

-- 统计每种关系的数量
MATCH ()-[r]->()
RETURN type(r), count(r)

路径查找

最短路径

-- 查找两个节点间的最短路径
MATCH path = shortestPath(
(a:Person {name: '张三'})-[:FRIEND*]-(b:Person {name: '王五'})
)
RETURN path, length(path) AS hops

-- 限制最大深度
MATCH path = shortestPath(
(a:Person {name: '张三'})-[:FRIEND*..10]-(b:Person {name: '王五'})
)
RETURN path

所有路径

-- 查找所有路径
MATCH paths = allShortestPaths(
(a:Person {name: '张三'})-[:FRIEND*]-(b:Person {name: '王五'})
)
RETURN paths

-- 查找特定长度的路径
MATCH path = (a:Person {name: '张三'})-[:FRIEND*3]-(b)
WHERE a <> b
RETURN path

路径函数

-- 获取路径中的节点
MATCH path = (a:Person)-[:FRIEND*2]->(b)
RETURN nodes(path)

-- 获取路径中的关系
MATCH path = (a:Person)-[:FRIEND*2]->(b)
RETURN relationships(path)

-- 获取路径长度
MATCH path = (a:Person)-[:FRIEND*2]->(b)
RETURN length(path)

条件表达式

CASE 表达式

-- 简单 CASE
MATCH (p:Person)
RETURN p.name,
CASE p.age
WHEN 20 THEN '二十岁'
WHEN 30 THEN '三十岁'
ELSE '其他年龄'
END AS ageGroup

-- 搜索 CASE
MATCH (p:Person)
RETURN p.name,
CASE
WHEN p.age < 18 THEN '未成年'
WHEN p.age >= 18 AND p.age < 60 THEN '成年人'
ELSE '老年人'
END AS ageGroup

COALESCE 函数

-- 返回第一个非空值
MATCH (p:Person)
RETURN p.name, coalesce(p.nickname, p.name, 'Unknown') AS displayName

列表操作

列表函数

-- 创建列表
RETURN [1, 2, 3, 4, 5] AS numbers

-- 范围列表
RETURN range(1, 10) AS numbers
RETURN range(1, 10, 2) AS oddNumbers

-- 列表大小
RETURN size([1, 2, 3]) AS listSize

-- 反转列表
RETURN reverse([1, 2, 3]) AS reversed

-- 提取子列表
RETURN [1, 2, 3, 4, 5][0..3] AS sublist

列表推导式

-- 过滤列表
WITH [1, 2, 3, 4, 5] AS numbers
RETURN [x IN numbers WHERE x > 2] AS filtered

-- 映射列表
WITH [1, 2, 3, 4, 5] AS numbers
RETURN [x IN numbers | x * 2] AS doubled

-- 过滤并映射
WITH [1, 2, 3, 4, 5] AS numbers
RETURN [x IN numbers WHERE x > 2 | x * 2] AS result

列表聚合

-- 使用 reduce 累加
WITH [1, 2, 3, 4, 5] AS numbers
RETURN reduce(sum = 0, x IN numbers | sum + x) AS total

-- 使用 extract 提取属性
MATCH (p:Person)
WITH collect(p) AS people
RETURN extract(x IN people | x.name) AS names

字符串函数

-- 字符串长度
RETURN length('Hello') AS strLength

-- 截取子串
RETURN substring('Hello World', 0, 5) AS sub

-- 替换
RETURN replace('Hello World', 'World', 'Neo4j') AS replaced

-- 转小写/大写
RETURN toLower('Hello') AS lower, toUpper('Hello') AS upper

-- 去除空白
RETURN trim(' Hello ') AS trimmed

-- 分割字符串
RETURN split('a,b,c', ',') AS parts

-- 连接字符串
RETURN join(['a', 'b', 'c'], '-') AS joined

数学函数

-- 绝对值
RETURN abs(-10) AS absolute

-- 四舍五入
RETURN round(3.14) AS rounded

-- 向上/向下取整
RETURN ceil(3.14) AS up, floor(3.14) AS down

-- 随机数
RETURN rand() AS random

-- 幂运算
RETURN pow(2, 3) AS power

-- 平方根
RETURN sqrt(16) AS squareRoot

日期时间函数

-- 当前日期时间
RETURN datetime() AS now
RETURN date() AS today
RETURN time() AS currentTime

-- 创建日期
RETURN date('2024-01-15') AS specificDate

-- 日期运算
RETURN date() + duration('P1D') AS tomorrow
RETURN date() - duration('P7D') AS lastWeek

-- 日期组件
WITH datetime() AS now
RETURN now.year, now.month, now.day, now.hour, now.minute

-- 格式化日期
RETURN datetime().epochMillis AS timestamp

模式理解(Pattern Comprehension)

-- 收集相关节点
MATCH (p:Person)
RETURN p.name, [(p)-[:FRIEND]->(friend) | friend.name] AS friends

-- 收集关系属性
MATCH (p:Person)
RETURN p.name, [(p)-[r:FRIEND]->() | r.since] AS friendSince

-- 带条件的模式理解
MATCH (p:Person)
RETURN p.name, [(p)-[:FRIEND]->(f) WHERE f.age > 25 | f.name] AS olderFriends

UNWIND 展开列表

-- 展开列表为行
WITH [1, 2, 3] AS numbers
UNWIND numbers AS num
RETURN num

-- 处理嵌套列表
WITH [[1, 2], [3, 4], [5, 6]] AS nested
UNWIND nested AS inner
UNWIND inner AS num
RETURN num

-- 实际应用:批量创建
WITH ['张三', '李四', '王五'] AS names
UNWIND names AS name
CREATE (p:Person {name: name})
RETURN p

调用过程(CALL)

-- 列出所有标签
CALL db.labels() YIELD label
RETURN label

-- 列出所有关系类型
CALL db.relationshipTypes() YIELD relationshipType
RETURN relationshipType

-- 列出所有属性键
CALL db.propertyKeys() YIELD propertyKey
RETURN propertyKey

-- 使用 APOC 库(需要安装)
CALL apoc.meta.stats() YIELD stats
RETURN stats

子查询

-- 使用 CALL 进行子查询
MATCH (p:Person)
CALL {
WITH p
MATCH (p)-[:FRIEND]->(friend)
RETURN count(friend) AS friendCount
}
RETURN p.name, friendCount

-- 使用 EXISTS 子查询
MATCH (p:Person)
WHERE EXISTS {
MATCH (p)-[:FRIEND]->(f) WHERE f.city = '北京'
}
RETURN p.name

综合示例

社交网络分析

-- 找出影响力最大的用户(朋友最多)
MATCH (p:Person)
OPTIONAL MATCH (p)-[:FRIEND]-(friend)
WITH p, count(friend) AS friendCount
ORDER BY friendCount DESC
RETURN p.name, friendCount
LIMIT 10

-- 找出共同好友
MATCH (a:Person {name: '张三'})-[:FRIEND]-(common)-[:FRIEND]-(b:Person {name: '李四'})
WHERE a <> b
RETURN common.name AS commonFriend

-- 计算聚类系数(朋友间也是朋友的比例)
MATCH (p:Person {name: '张三'})-[:FRIEND]-(friend)
WITH p, collect(friend) AS friends, count(friend) AS friendCount
MATCH (f1)-[:FRIEND]-(f2)
WHERE f1 IN friends AND f2 IN friends AND f1 <> f2
RETURN friendCount, count(*)/2.0 / (friendCount * (friendCount - 1) / 2.0) AS clusteringCoefficient

推荐系统

-- 基于共同好友的推荐
MATCH (user:Person {name: '张三'})-[:FRIEND]-(friend)-[:FRIEND]-(potential)
WHERE NOT (user)-[:FRIEND]-(potential) AND user <> potential
WITH potential, count(friend) AS commonFriends
ORDER BY commonFriends DESC
RETURN potential.name, commonFriends
LIMIT 5

-- 基于兴趣的推荐
MATCH (user:Person {name: '张三'})-[:LIKES]->(interest)<-[:LIKES]-(similar)
WHERE user <> similar
WITH similar, count(interest) AS commonInterests
ORDER BY commonInterests DESC
RETURN similar.name, commonInterests
LIMIT 5

性能优化提示

  1. 使用参数化查询

    MATCH (p:Person {name: $name})
    RETURN p
  2. 限制深度遍历

    -- 好的做法:限制深度
    MATCH (p)-[:FRIEND*1..5]-(other)

    -- 避免:无限制深度
    MATCH (p)-[:FRIEND*]-(other)
  3. 使用 PROFILE 分析查询

    PROFILE MATCH (p:Person)-[:FRIEND]->()
    RETURN count(p)
  4. 合理使用索引

    -- 为常用查询属性创建索引
    CREATE INDEX person_name FOR (p:Person) ON (p.name)

下一步

掌握了高级查询后,继续学习 索引与约束,了解如何优化查询性能和保证数据完整性。