
你有没有过这样的经历?刚下载一个社交 App,它就给你推荐了多年未见的老同学,或是隔壁部门可能有过一面之缘的同事。你心里不禁犯嘀咕:“它怎么知道的?”
其实,这背后很可能是图数据库在默默工作。它把整个社交平台制造成一张巨大的关系网,通过分析这张网里错综复杂的连接,来做出更懂你的推荐。
今天,NebulaGraph 就通过一个简单的 Demo,带你一窥这位“关系大师”是怎么工作的。
Demo 链接
https://www.nebula-graph.com.cn/demo
欢迎在 NebulaGraph 官网体验多场景 Demo,亲自动手验证图数据库的能力~
一、图模型设计
💡在实际使用中,可对 Schema 进行相应修改与管理,为便于在线体验,本 Demo 暂不支持。

在正式推理开始前,我们得先知道上文提到的关系网是怎么搭起来的。
你可以把这张网想象成三个简单的部分:
人(节点):代表每个用户。
关系(边):“好友”、“关注”、“点赞”、“评论”这些让每个用户之间,产生关系的互动行为。
内容/社群/Tag(节点):比如一篇“旅游攻略”,或者一个“篮球爱好者群”。
💡在真实的业务里, 社群通常可以作为用户的一个属性来存储。但在我们这个演示里,特意将其单独建模成了一个节点。这是为了让你更直观地看清“用户 – 社群 – 内容”这条完整链条,感受图数据库在多跳关系查询上的优势。实际生产环境里,完全可以根据业务需求灵活调整模型。
图数据库要做的,就是把它们之间千丝万缕的联系,全部存进去,并且让这些关系可以被随时查询和分析。
节点类型包括下表:

边类型包括下表:

了解完图数据库要做什么后,我们首先要在图数据库中,把基本规则创建起来。
首先,创建图类型与图空间,并执行以下语句定义节点、边结构及属性:
CREATE GRAPH TYPE IF NOT EXISTS `social_recommendation` AS {NODE TYPE `Person` (LABEL `Person`{`person_id` STRING NOT NULL, `name` STRING DEFAULT NULL, `city` STRING DEFAULT NULL, `register_time` ZONED DATETIME DEFAULT NULL, PRIMARY KEY (`person_id`)}),NODE TYPE `Community` (LABEL `Community`{`community_id` STRING NOT NULL, `name` STRING DEFAULT NULL, `topic` STRING DEFAULT NULL, `created_time` ZONED DATETIME DEFAULT NULL, PRIMARY KEY (`community_id`)}),NODE TYPE `Content` (LABEL `Content`{`content_id` STRING NOT NULL, `title` STRING DEFAULT NULL, `category` STRING DEFAULT NULL, `publish_time` ZONED DATETIME DEFAULT NULL, PRIMARY KEY (`content_id`)}),NODE TYPE `UserTag` (LABEL `UserTag`{`tag_name` STRING NOT NULL, PRIMARY KEY (`tag_name`)}),EDGE TYPE `Friend` (`Person`)-[LABEL `Friend`{`since_time` ZONED DATETIME NOT NULL, `closeness` DOUBLE DEFAULT NULL, MULTIEDGE KEY(`since_time`)}]->(`Person`),EDGE TYPE `MemberOf` (`Person`)-[LABEL `MemberOf`{`join_time` ZONED DATETIME NOT NULL, `role_name` STRING DEFAULT NULL, MULTIEDGE KEY(`join_time`)}]->(`Community`),EDGE TYPE `Forward` (`Person`)-[LABEL `Forward`{`forward_time` ZONED DATETIME NOT NULL, `action_weight` DOUBLE DEFAULT NULL, MULTIEDGE KEY(`forward_time`)}]->(`Content`),EDGE TYPE `Like` (`Person`)-[LABEL `Like`{`like_time` ZONED DATETIME NOT NULL, `score` DOUBLE DEFAULT NULL, MULTIEDGE KEY(`like_time`)}]->(`Content`),EDGE TYPE `Comment` (`Person`)-[LABEL `Comment`{`comment_time` ZONED DATETIME NOT NULL, `content_text` STRING DEFAULT NULL, MULTIEDGE KEY(`comment_time`)}]->(`Content`),EDGE TYPE `FollowKOL` (`Person`)-[LABEL `FollowKOL`{`follow_time` ZONED DATETIME NOT NULL, `interaction_level` DOUBLE DEFAULT NULL, MULTIEDGE KEY(`follow_time`)}]->(`Person`),EDGE TYPE `HasInterest` (`Person`)-[LABEL `HasInterest`{`weight` DOUBLE DEFAULT NULL}]->(`UserTag`),EDGE TYPE `Cites` (`Content`)-[LABEL `Cites`{`cite_time` ZONED DATETIME DEFAULT NULL}]->(`Content`)};CREATE GRAPH `social_recommendation` :: `social_recommendation`;
二、数据导入
💡本 Demo 仅预置 30 名用户及数千条社交关系,实际导入时,数据量可达千亿级甚至更多。
-- 导入用户节点TABLE `person_data` { `person_id`, `name`, `city`, `register_time` } =("p001", "Alice", "Beijing", "2024-01-05T09:00:00 +0800"), ("p002", "Bob", "Beijing", "2024-01-06T10:30:00 +0800"), ("p003", "Charlie", "Beijing", "2024-01-07T11:00:00 +0800"), ("p004", "David", "Beijing", "2024-01-08T14:20:00 +0800"), ("p005", "Evan", "Beijing", "2024-01-09T15:00:00 +0800"), ("p006", "Fiona", "Beijing", "2024-01-10T16:45:00 +0800"), ("p007", "George", "Beijing", "2024-01-11T09:15:00 +0800"), ("p008", "Hannah", "Beijing", "2024-01-12T10:30:00 +0800"), ("p009", "Ivan", "Beijing", "2024-01-13T11:45:00 +0800"), ("p010", "Julia", "Beijing", "2024-01-14T13:00:00 +0800"),("p011", "Kevin", "Shanghai", "2024-01-15T09:00:00 +0800"), ("p012", "Linda", "Shanghai", "2024-01-16T10:30:00 +0800"), ("p013", "Mike", "Shanghai", "2024-01-17T11:00:00 +0800"), ("p014", "Nancy", "Shanghai", "2024-01-18T14:20:00 +0800"), ("p015", "Oscar", "Shanghai", "2024-01-19T15:00:00 +0800"), ("p016", "Paula", "Shanghai", "2024-01-20T16:45:00 +0800"), ("p017", "Quinn", "Shanghai", "2024-01-21T09:15:00 +0800"), ("p018", "Rachel", "Shanghai", "2024-01-22T10:30:00 +0800"), ("p019", "Steve", "Shanghai", "2024-01-23T11:45:00 +0800"), ("p020", "Tina", "Shanghai", "2024-01-24T13:00:00 +0800"),("p021", "Uma", "Hangzhou", "2024-01-25T09:00:00 +0800"), ("p022", "Victor", "Hangzhou", "2024-01-26T10:30:00 +0800"), ("p023", "Wendy", "Hangzhou", "2024-01-27T11:00:00 +0800"), ("p024", "Xavier", "Hangzhou", "2024-01-28T14:20:00 +0800"), ("p025", "Yvonne", "Hangzhou", "2024-01-29T15:00:00 +0800"), ("p026", "Zack", "Hangzhou", "2024-01-30T16:45:00 +0800"), ("p027", "Amy", "Hangzhou", "2024-01-31T09:15:00 +0800"), ("p028", "Brian", "Hangzhou", "2024-02-01T10:30:00 +0800"), ("p029", "Cathy", "Hangzhou", "2024-02-02T11:45:00 +0800"), ("p030", "Derek", "Hangzhou", "2024-02-03T13:00:00 +0800")USE `social_recommendation`FOR re IN `person_data`INSERT (@`Person` {`person_id`: re.`person_id`, `name`: re.`name`, `city`: re.`city`, `register_time`: CAST(re.`register_time` AS ZONED DATETIME)})-- 导入社群节点TABLE `community_data` { `community_id`, `name`, `topic`, `created_time` } =("c001", "AI与大模型研究", "Technology", "2023-12-01T08:00:00 +0800"), ("c002", "电商运营交流", "Business", "2023-12-05T09:00:00 +0800"), ("c003", "硬核数码科技", "Hardware", "2023-12-10T10:00:00 +0800"), ("c004", "城市慢生活", "Lifestyle", "2023-12-15T11:00:00 +0800")USE `social_recommendation`FOR re IN `community_data`INSERT (@`Community` {`community_id`: re.`community_id`, `name`: re.`name`, `topic`: re.`topic`, `created_time`: CAST(re.`created_time` AS ZONED DATETIME)})-- 导入内容节点TABLE `content_data` { `content_id`, `title`, `category`, `publish_time` } =("ct001", "图数据库在AI时代的机遇", "Tech", "2024-03-01T08:00:00 +0800"), ("ct002", "2024电商新风向标", "Business", "2024-03-02T09:00:00 +0800"), ("ct003", "深度解析PageRank算法", "Tech", "2024-03-03T10:00:00 +0800"), ("ct004", "我的极简桌面搭配", "Life", "2024-03-04T11:00:00 +0800"), ("ct005", "机械键盘轴体科普", "Hardware", "2024-03-05T12:00:00 +0800"),("ct006", "LLM微调实战指南", "Tech", "2024-03-06T13:00:00 +0800"), ("ct007", "直播带货的底层逻辑", "Business", "2024-03-07T14:00:00 +0800"), ("ct008", "周末探店:魔都咖啡", "Life", "2024-03-08T15:00:00 +0800"), ("ct009", "显卡选购避坑指南", "Hardware", "2024-03-09T16:00:00 +0800"), ("ct010", "如何高效管理时间", "Life", "2024-03-10T17:00:00 +0800")USE `social_recommendation`FOR re IN `content_data`INSERT (@`Content` {`content_id`: re.`content_id`, `title`: re.`title`, `category`: re.`category`, `publish_time`: CAST(re.`publish_time` AS ZONED DATETIME)})

三、关键查询示例
💡在 Demo 中,已经完成了 schema 设计和数据导入,大家可以在 console 页面,任意探索社交场景的不同语句、玩法。
1. 查找某人的 1-3 度好友
目的:全面掌握目标用户的社交网络范围,发现潜在的兴趣传播路径和社群影响力范围。
USE `social_recommendation`MATCH p=(src@`Person` {`person_id`: "p001"})-[:`Friend`]-{1,3}(friend)RETURN p

基于图的解释:该图展示了从用户 p001 出发,经过 1 到 3 跳好友关系能到达的所有用户节点及路径。
2. 熟人好友推荐
目的:基于“朋友的朋友是朋友”的社交理论,通过共同好友数量为用户推荐可能认识的人。
USE `social_recommendation`MATCH (src@`Person` {`person_id`: "p001"})-[:`Friend`]-(mutual_friend)-[:`Friend`]-(candidate)WHERE candidate.`person_id` <> "p001" // 排除自己AND NOT EXISTS((src)-[:`Friend`]-(candidate)) // 排除已经是好友的人RETURN candidate.`person_id` AS recommended_friend,candidate.`name` AS name,count(mutual_friend) AS mutual_friends_countORDER BY mutual_friends_count DESCLIMIT 10

基于表格的解释:为用户 p001 推荐共同好友最多的前 10 位潜在朋友。mutual_friends_count 越高,推荐的理由越充分,用户接受推荐的概率越大。
3. 兴趣社群推荐 (基于朋友圈子)
目的:通过分析用户好友的社群加入行为,推测用户可能也感兴趣的社群,实现社群推荐。
USE `social_recommendation`MATCH (src@`Person` {`person_id`: "p001"})-[:`Friend`]-(friend)-[:`MemberOf`]-(community)WHERE NOT EXISTS((src)-[:`MemberOf`]-(community))RETURN community.`name` AS community_name,community.`topic` AS topic,count(friend) AS friends_joined_countORDER BY friends_joined_count DESCLIMIT 5

基于表格的解释:为用户 p001 推荐其好友们最常加入的 5 个社群。friends_joined_count 越高,说明该社群在当前用户的社交圈子中越流行,推荐价值越高。
4. 基于相似行为的内容推荐
目的:找到与目标用户有相同转发行为的相似用户,然后将这些相似用户点赞过的其他内容推荐给目标用户,实现协同过滤推荐。
USE `social_recommendation`MATCH (src@`Person` {`person_id`: "p002"})-[:`Forward`]->(common_content)<-[:`Forward`]-(similar_user)-[:`Like`]->(recommended_content)WHERE NOT EXISTS((src)-[:`Like`]->(recommended_content))AND NOT EXISTS((src)-[:`Forward`]->(recommended_content))RETURN recommended_content.`title` AS content_title,similar_user.`name` AS liked_by_user,count(common_content) AS similarity_scoreORDER BY similarity_score DESCLIMIT 10

基于表格的解释:为用户 p002 推荐由与其转发行为最相似的 10 位用户所喜欢的内容。similarity_score 代表推荐内容与用户兴趣的相似度权重,liked_by_user 字段提供了推荐理由。
四、总结
综上所述,图数据库的核心理念其实并不复杂,其实就是将“人与人”、“人与内容”之间的关系作为一等公民进行存储与计算。然而,正是这一思路的转变,为推荐系统带来了质的变化。
回顾前文所述的所有查询示例,可以清晰地看到,借助 NebulaGraph 构建的社交兴趣关联网络,推荐系统在以下四个维度上实现了显著提升:
1. 发现多层社交路径:突破传统推荐系统局限于个体历史行为的视野,图数据库可沿好友、关注等链路穿透至三度、四度关系,挖掘深层社交联系与影响力传导路径。
2. 提供可量化指标:基于共同好友数、相似行为频次等结构化数据,为每条推荐提供可量化的信任度依据,如“你们有8位共同好友”,让推荐结果有据可循。
3. 统一查询模式:熟人推荐、社群推荐、协同过滤等多样化策略,均可通过图数据库的统一查询语言实现,无需为每种逻辑单独搭建技术栈,显著降低开发复杂度。
4. 天然路径回溯:图数据库可清晰展示推荐结果的完整产生链路(如“A的好友B点赞了C,故推荐C给A”),为策略优化与用户沟通提供透明化支撑。
总而言之,图数据库以一种更贴近人类认知直觉的方式,将世界视作一张相互连接的网络,正是这一视角的转换,使社交推荐从“猜你喜欢”进化为“基于关系的精准匹配”。如果您的产品正面临社交推荐的效率瓶颈,不妨从绘制一张关系图谱开始探索新的可能。
💡本 Demo 展示了基础查询,仅作为简单场景下的 NebulaGraph 使用参考。在实际生产环境中,还可结合 PageRank、标签传播、连通分量等图算法,实现更智能的社区发现与兴趣扩散。
✦
如果你觉得 NebulaGraph 能帮到你,或者你只是单纯支持开源精神,可以在 GitHub 上为 NebulaGraph 点个 Star!
每一个 Star 都是对我们的支持和鼓励✨
GitHub:https://github.com/vesoft-inc/nebula
官网:https://www.nebula-graph.com.cn/
论坛:https://discuss.nebula-graph.com.cn/
✦
✦

扫码添加
可爱星云
技术交流
资料分享



NebulaGraph 用户案例
✦
Why Graph Database?⬇️
风控场景:普适智能|中证数智|BlockSec|携程|Airwallex|众安保险|中国移动|Akulaku|邦盛科技|360数科|BOSS直聘|金蝶征信|快手|青藤云安全
平台建设:博睿数据|携程|众安科技|微信|OPPO|vivo|美团|百度爱番番|携程金融|普适智能|BIGO
知识图谱:普适智能|中证数智|中医药大学|企查查|腾讯音乐|中科大脑|泰康在线|苏宁|微澜|同花顺|携程酒店
营销推荐:阿里妈妈
GraphRAG:中科数睿
✦
✦
夜雨聆风