Neo4j 做关系推荐:Cypher 三度好友查询实战

举报
yd_275379215 发表于 2026/11/09 09:10:05 2026/11/09
【摘要】 社交产品要做"可能认识的人"推荐,第一版用关系库写的:好友的好友(二度)SQL套两层join还能跑,产品要三度关系加共同好友数排序,SQL变成了五层嵌套的怪物,跑了40秒。迁到Neo4j后同样的逻辑Cypher几行、200毫秒,这次实战让我理解了图数据库的适用边界。模型设计先想清楚。节点是User(带uid、city属性),关系是KNOWS(带since、weight)。图建模的原则是"关系...

社交产品要做"可能认识的人"推荐,第一版用关系库写的:好友的好友(二度)SQL 套两层 join 还能跑,产品要三度关系加共同好友数排序,SQL 变成了五层嵌套的怪物,跑了 40 秒。迁到 Neo4j 后同样的逻辑 Cypher 几行、200 毫秒,这次实战让我理解了图数据库的适用边界。

模型设计先想清楚。节点是 User(带 uid、city 属性),关系是 KNOWS(带 since、weight)。图建模的原则是"关系是一等公民":KNOWS 是物理存在的边(指针式的连通),不是关系库里要用 join 现场推导的外键。三度好友查询的 Cypher:

// 三度关系推荐:认识你的人认识的人再认识,但不是你已认识的
MATCH (me:User {uid: $uid})-[:KNOWS*2..3]-(friend:User)
WHERE friend.uid <> $uid
  AND NOT (me)-[:KNOWS]-(friend)          // 排除已是好友
  AND friend.city = $city                  // 同城加权
WITH friend, count(DISTINCT friend) AS paths,
     length(shortestPath((me)-[:KNOWS*]-(friend))) AS degree
RETURN friend.uid, friend.name,
       paths * 1.0 / degree AS score       // 路径多且近者优先
ORDER BY score DESC
LIMIT 20;

查询里两个设计点。可变长关系 [:KNOWS*2..3] 是图查询的灵魂,等价于 SQL 里不可想象的多层递归 join,Neo4j 沿边遍历是本地指针跳转,成本和度数相关而不是和全图规模相关——这是 200ms 对 40s 的来源。NOT (me)-[:KNOWS]-(friend) 的反模式匹配用来排除已认识的人,写法上是"模式即条件"的图思维,SQL 里对应 NOT EXISTS 子查询但执行代价完全不同。

工程化的配套也有讲究。属性索引 CREATE INDEX FOR (u:User) ON (u.uid) 保证起点定位 O(1);遍历深度要设上限(这里 3 度封顶),无界的可变长遍历在大图上可能失控;命中高频的推荐查询加了 5 分钟 TTL 的应用层缓存。数据导入用 neo4j-admin 的 CSV 批量导入,2000 万用户加 8 亿关系 40 分钟灌完,比逐条 CREATE 快两个数量级。

图运维的配套也提一句:Neo4j 的备份用 neo4j-admin dump 在线快照,千万节点级十分钟内完成;APOC 插件几乎必装,批量导入、路径扩展、图算法的瑞士军刀。图数据库的生态比关系库薄,周边工具的成熟度要在选型时一起评估,不然落地时处处补课。

最后说边界:图数据库不是关系库的替代,是补充。我们的订单、账目仍然在 MySQL,只有"关系密集"的数据(好友、权限继承、风控关联网络)值得进图——判断标准是 join 深度:业务查询常态化要两层以上 join 且以连通性为核心,图的收益才开始兑现。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。