为了方便用户能够熟悉图计算服务GraphCompute,我们提供一份完整的Demo数据、查询Query和文档指南,帮助用户快速搭建一个图计算应用,并提供百万级别数据量的多度好友关系查询&分析能力。
图计算是什么?
图计算服务(GraphCompute)基于阿里巴巴自主研发的图引擎,提供一站式图计算解决方案,专注OLAP能力的扩展和支持,通过自研的高性能算子,让用户快速接入数据和完成图技术探索。结合阿里巴巴在电商、安全和社交等多个行业领域的积累,为全球企业及开发者提供图技术服务。
【好友推荐】为什么要用图计算
社交类场景的数据模型属于典型的图结构,图计算可以为社交类业务提供天然的图模型支持,更加完美表达各种关系的数据。使用图计算,可以显著提升社交类业务程序的开发效率和质量,减少数据关系的转换和计算的额外损耗。
以社交关系为例,不仅是好友查询,在“初始用户推荐、好友推荐、聊天查询、关联主题”等多种场景中都能运用图来建模。图技术在好友查询中仅需要几毫秒的时间,它将好友定义成节点,将好友与好友之间的关系定义成边,图计算产品能够以“点、边”的查询方式,更加高效的表达并分析这复杂图结构下的数据关系和结果。
【好友推荐】业务逻辑怎么构建
某款社交APP,是一款年轻人交友软件,通过虚拟头像,匿名社交,即时匹配、连麦派对、声控接唱、兴趣测试等功能,从相遇开始,拒绝尬聊。该业务提供了“心灵匹配”功能,主要技术诉求是基于图计算能够提供三度好友推荐给“心灵匹配”。
根据业务的特点进行抽象定义,最终的业务逻辑可以理解为:
-
查询的业务场景:A- B - C -D 三跳好友关系
-
需要获取到三跳后,对所有好友进行路径权重加分,最终得到一个推荐好友的排序列表

【好友推荐】图模型创建
根据图查询的业务场景:A- B - C -D 三跳好友关系,通过模型的抽取和总结,最终我们确定的图模型结构是如下结构:User代表用户节点,节点信息中包括用户属性(生日、性别)、relation代表用户之间的关系,代表他们的关系(关系权重-PS:关系权重基于离线计算或者分析可得)

Relation 关系表达,就是典型的U2U思路,找到与其兴趣相似的活跃用户,将后者的行为作为前者行为序列的补充,可以对于低活跃用户相似偏好的推荐。
U2U扩展的方法也有好几类:
|
方法 |
优点 |
缺点 |
|
1.user-based的协同过滤 |
推荐的发现性好。 |
难以引入side information,比如关注的人员、兴趣点、学校或用户的基础信息,年龄、购买力等;且数据稀疏对该类算法的影响较大。 |
|
2. 基于user embedding,进行相似用户的Top k检索 |
在挖掘user embedding的过程中可以引入较多side information。 |
相似用户的Top k检索鲁棒性较差,计算资源消耗大。 |
|
3. 引入用户向量聚簇,变成相似用户簇的Top k检索 |
相似簇推荐相较于相似用户的推荐,稳定性较高,计算开销减少。 |
基于用户单向量聚簇,容易忽略用户行为横跨多类目的特性,得到的商品列表较为单一。 |
如何创建图应用
根据图查询的业务场景:A- B - C -D 三跳好友关系,通过模型的抽取和总结,最终我们确定的图模型结构是如下结构:User代表用户节点,节点信息中包括用户属性(生日、性别)、relation代表用户之间的关系,代表他们的关系(关系权重-PS:关系权重基于离线计算或者分析可得)
1、创建集群
在图计算服务购买页面,配置以下参数:地域(如华北2(北京)、华东2(上海)等)、实例名称、用户名、用户密码、可用区数量、主可用区、网络类型(选择专有网络)、专有网络、虚拟交换机、购买规格(独享通用型/独享计算型/独享存储型)、分片规格、副本数、分片数以及购买时长,完成后提交购买。
2、定义图模型、配置节点、关系表
|
定义图模型 |
配置节点 |
配置关系表 |
|
|
示例使用: MaxCompute源表:【igraph_mock.vertex_user_demo】 节点表中包括123074个用户 |
示例使用: MaxCompute源表:【igraph_mock.edge_relation_demo】 关系表中包括399879条关系边 |
1)定义图模型
1、创建【新增 - 图】定义图名和描述;
图名:【user_relation_graph】 ,后续Gremlin查询语句中需要指定访问的图配置名称。
2、【图编辑】页面【新增点】创建User节点表
3、【图编辑】页面【User节点表】直接创建relation关系
右键单击User节点,在弹出菜单中选择增加边,创建relation关系。
2)配置节点属性
在增加数据配置(点)对话框中,设置点名称为user,数据来源选择MaxCompute数据源,源表项目为igraph_mock,源表名称为vertex_user_demo,索引类型选择KV。字段结构包括id(INT64,pkey)、gender(STRING,默认值0)、starsign(STRING,默认值0)。配置完成后,单击提交。
3)配置关系属性
在增加数据配置(边)对话框中,设置边名称为relation,边属性选择单向边,关联节点均选择user。数据来源选择MaxCompute数据源,源表项目为igraph_mock,源表名称为edge_relation_demo。字段结构包括from_id(INT64,起点字段)、to_id(INT64,终点字段)、score(DOUBLE,默认值0.0)。配置完成后,单击提交。
注意:如果后续需要基于关系数据执行图算法相关任务,请关闭【索引优化】的配置。
在数据配置(边)对话框底部,找到索引优化开关并将其关闭。
4)发布图配置
在图编辑页面顶部,单击发布按钮,将图配置发布到线上环境。
3、发布索引
1)批量回流
图计算服务底层服务是通过分布式图计算引擎来提供服务,在每次图配置更新正式发布后,都需要进行一次数据回流操作。我们提供了一键化的【批量回流】功能,进行线上数据结构的快速变更。
在批量触发索引构建对话框中,勾选需要构建索引的表(如user、pagerank_1011_result、wcc_1011_result),选择对应的分区版本和增量时间戳,然后执行索引构建。
2)特定表回流
在图编辑页面中,右键单击需要回流的节点(如user),在弹出菜单中选择触发索引构建或增量数据写入,对特定表进行单独的数据回流操作。
4、图查询
通过前面的步骤,图计算应用及数据已经准备完成,下面就可以进行图数据的查询和分析;
可以通过【图探索】-进行探索式交互或者控制台Gremlin语句查询;
|
通过探索式查询页面,在搜索框中输入节点ID(如用户ID),系统以图形化方式展示该节点的关联关系网络,支持拖拽和缩放等交互操作。 |
通过控制台查询页面,输入Gremlin查询语句并查看JSON格式的查询结果,支持参考查询语法文档和更新语法文档。 |
【好友推荐】测试Case
1、根据Userid查询用户详情:
g("user_relation_graph").V("7949635553727122101").hasLabel("users")
查询结果:
{
"result": [
{
"data": [
{
"value": [
{
"label": "user",
"gender": "1",
"id": "7949635553727122101",
"starsign": "Aries"
}
],
"labels": [
[]
]
}
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}
2、批量查询一批Userid的用户详情
g("user_relation_graph").V("2443269531561029504;4315033251719520021;6045530619721418713;-2441936916298108531;-6187501937134616998;-7902352812594818920;8829494226614398819;-788398966410862160").hasLabel("user")
查询结果:
{
"data": [
{
"label": "user",
"gender": "1",
"id": "-2441936916298108531",
"starsign": "Cancer"
},
{
"label": "user",
"gender": "1",
"id": "-6187501937134616998",
"starsign": "Gemini"
},
{
"label": "user",
"gender": "0",
"id": "-788398966410862160",
"starsign": "Capricorn"
},
{
"label": "user",
"gender": "0",
"id": "-7902352812594818920",
"starsign": "Aquarius"
},
{
"label": "user",
"gender": "0",
"id": "2443269531561029504",
"starsign": "Pisces"
},
{
"label": "user",
"gender": "1",
"id": "4315033251719520021",
"starsign": "Pisces"
},
{
"label": "user",
"gender": "1",
"id": "6045530619721418713",
"starsign": "Pisces"
},
{
"label": "user",
"gender": "1",
"id": "8829494226614398819",
"starsign": "Aquarius"
}
],
"error_info": [],
"trace_info": {}
}
3、查询用户的一度关系并且排序计算
g("user_relation_graph").E("7949635553727122101").hasLabel("relation").order().by("score",decr).limit(10).values("to_id")
查询结果:
{
"result": [
{
"data": [
"2557390182698651469",
"-5910095803510830870",
"-8777626058260080543",
"-3326503472333052856",
"-5628868613588358018",
"5693972407819734988",
"3169032466213709540",
"-6273932137952248996",
"85024782667881542",
"2490097926641478897"
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}
4、查询用户的三度好友中星座为白羊座的好友
g("user_relation_graph").E("-2441936916298108531").hasLabel("relation").outE().outE().inV().filter("starsign=\"Aries\"")
查询结果:
查询返回4638条结果,每条记录包含label(user)、gender、id和starsign(Aries)字段,表示该用户三度好友中共有4638名白羊座用户。
5、查询用户7949635553727122101好友的星座人数分布
g("user_relation_graph").E("7949635553727122101").hasLabel("relation").inV().groupCount().by("starsign")
查询结果:
{
"result": [
{
"data": [
{
"\"Aquarius\"": "7",
"\"Aries\"": "10",
"\"Cancer\"": "1",
"\"Capricorn\"": "3",
"\"Gemini\"": "3",
"\"Leo\"": "2",
"\"Libra\"": "2",
"\"Pisces\"": "9",
"\"Sagittarius\"": "7",
"\"Taurus\"": "4",
"\"Virgo\"": "2"
}
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}
6、查询用户7949635553727122101好友的星座分数分布
g("user_relation_graph").withSack(supplier(normal,"0.0"),Splitter.identity,Operator.sum).E("7949635553727122101").hasLabel("relation").sack(Operator.sum).by("score").inV().group().by("starsign").by(sack().sum())
查询结果:
{
"result": [
{
"data": [
{
"\"Aquarius\"": "99.44964174192042",
"\"Aries\"": "171.6614835163086",
"\"Cancer\"": "15.8359302136816",
"\"Capricorn\"": "42.44029297266677",
"\"Gemini\"": "34.2056092615523",
"\"Leo\"": "16.46936742222886",
"\"Libra\"": "24.07061392479605",
"\"Pisces\"": "129.85462775218915",
"\"Sagittarius\"": "86.14746036242798",
"\"Scorpio\"": "6.33437208547264",
"\"Taurus\"": "41.80685576411946",
"\"Virgo\"": "33.572172053005"
}
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}
7、查询用户-2441936916298108531三度好友中星座为白羊座的好友,计算路径权重总分,按得分降序排列,并取前10名
g("user_relation_graph").withSack(supplier(normal,"0.0"),Splitter.identity,Operator.sum).E("-2441936916298108531").hasLabel("relation").sack(Operator.sum).by("score").outE().sack(Operator.sum).by("score").outE().sack(Operator.sum).by("score").inV().filter("starsign=\"Aries\"").values("id").barrier().dedup().order().by(sack(),decr).limit(10)
查询结果:
{
"result": [
{
"data": [
"-4985651325249407669",
"-966745601209007179",
"300594519935616602",
"8616477414455953382",
"3410211067444088094",
"7361520262922301828",
"4419627442674893942",
"1684980613157243612",
"-3968869064747091877",
"7376060565223003509"
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}
高阶能力 - 高性能全图统计能力
业务功能:需要对用户进行全局的统计和计算,图计算服务在图查询能力的基础之上,集成了倒排查询。
1、用户表从【KV索引】调整为【INDEX】倒排索引,提交表配置保存;
在节点配置中,将索引类型切换为Inverted INDEX(倒排索引),配置字段结构包含id(STRING)和component_id(STRING,默认值0),并在index字段区域添加id和component_id的索引配置,其中id设为pkey。
2、执行图配置的【保存】和【发布】功能;
3、图运维 - 索引构建
在图编辑页面中,右键单击节点(如user),在弹出菜单中选择触发索引构建,执行索引构建操作。待索引构建完成后,即可前往图探索进行图查询。
测试case:
1、查询所有白羊座的用户
g("user_relation_graph").V().hasLabel("user").indexQuery("{\"match\":{\"starsign\":\"Aries\"},\"config\":{\"seek_count_limit_per_shard\":100000,\"search_count_limit_per_shard\":100000}}")
查询结果:
查询返回36867条白羊座用户记录,每条记录包含label(user)、gender、id和starsign(Aries)字段。
2、查询所有男性用户的星座分布(为了保证性能,进行了limit 统计截断)
g("user_relation_graph").V().hasLabel("user").indexQuery("{\"match\":{\"gender\":\"1\"},\"config\":{\"seek_count_limit_per_shard\":100000,\"search_count_limit_per_shard\":100000}}").groupCount().by("starsign")
查询结果:
{
"result": [
{
"data": [
{
"\"Aquarius\"": 825,
"\"Aries\"": 640,
"\"Cancer\"": 923,
"\"Capricorn\"": 848,
"\"Gemini\"": 773,
"\"Leo\"": 821,
"\"Libra\"": 522,
"\"Pisces\"": 2397,
"\"Sagittarius\"": 491,
"\"Scorpio\"": 501,
"\"Taurus\"": 739,
"\"Virgo\"": 520
}
],
"error_info": [
],
"trace_info": {
}
}
],
"error_info": [
]
3、查询好友最多的100名白羊座男性用户
g("user_relation_graph").V().hasLabel("user").indexQuery("{\"and\":[{\"match\":{\"gender\":\"1\"}\},\{\"match\":{\"starsign\":\"Aries\"}}],\"config\":{\"seek_count_limit_per_shard\":100000,\"search_count_limit_per_shard\":100000}}").limit(10000).outE().groupCount().by("from_id").unfold().order().by(select(Column.values),decr).limit(100)
查询结果:
{
"result": [
{
"data": [
{
"-7032647615083234229": "50"
},
{
"-5722782251601168066": "50"
},
{
"-5335242748220558153": "50"
},
{
"-8676408452255309391": "50"
},
{
"-6047928004364318541": "50"
},
{
"-5344466669668822162": "50"
},
{
"-6190401221243138849": "50"
},
{
"-4827852736929428415": "50"
},
{
"-5307302829373746633": "50"
},
{
"-5475401520922089187": "50"
},
{
"-8017336865667734219": "50"
},
{
"-8152630370117271740": "50"
},
{
"-7004109459328652310": "50"
},
{
"-7817593255334792111": "50"
},
{
"-5272574182922494022": "50"
},
{
"-8523896507246731100": "50"
},
{
"-5938745235467206212": "50"
},
{
"-8438867826624678384": "50"
},
{
"-4405449005585220943": "50"
},
{
"-9126301390881979643": "50"
},
{
"-5382489933968271711": "50"
},
{
"-8841373379965641987": "50"
},
{
"-5302202017699941647": "50"
},
{
"-6248244606214120159": "50"
},
{
"-6711633791333564554": "50"
},
{
"-7315782827574470472": "50"
},
{
"-9031277985752489187": "50"
},
{
"-9022869359443119815": "50"
},
{
"-8369470302541518920": "50"
},
{
"-6142766699127849771": "50"
},
{
"-8655738446138261193": "50"
},
{
"-8646149194767113790": "50"
},
{
"-9097183937680782346": "50"
},
{
"-4641376756135904334": "50"
},
{
"-9081172527938898024": "50"
},
{
"-7137344541799001227": "50"
},
{
"-8491934123275310192": "50"
},
{
"-5656245743850590165": "50"
},
{
"-8448876639884702547": "50"
},
{
"-8921032424157220292": "50"
},
{
"-8886790874757451152": "50"
},
{
"-4170067740591839020": "50"
},
{
"-8412401447690411889": "50"
},
{
"-6935600597565680532": "50"
},
{
"-6465292696804515998": "50"
},
{
"-4580178566813967734": "50"
},
{
"-8337980039891383510": "50"
},
{
"-6750094915823112945": "50"
},
{
"-8271130662107074869": "50"
},
{
"-4313989045148439251": "50"
},
{
"-7072971882028192758": "50"
},
{
"-6081673847669716322": "50"
},
{
"-8215720337033905961": "50"
},
{
"-4511660190549716707": "50"
},
{
"-6954636645089290492": "50"
},
{
"-5470987491723790775": "50"
},
{
"-8693909718856724970": "50"
},
{
"-9172299426900892564": "50"
},
{
"-6142070315717702174": "50"
},
{
"-8683222889153361552": "50"
},
{
"-6061245317590715601": "50"
},
{
"-8680938277196498242": "50"
},
{
"-6382251776295701372": "50"
},
{
"-7953204420754362673": "50"
},
{
"-5390210842719212579": "50"
},
{
"-7836046658486786908": "50"
},
{
"-7151222483126499509": "50"
},
{
"-7824880497332818548": "50"
},
{
"-5914268273571897378": "50"
},
{
"-6703760236487855527": "50"
},
{
"-6251439297928817838": "50"
},
{
"-7764254764054046817": "50"
},
{
"-4147078275545366756": "50"
},
{
"-8961736465346823903": "50"
},
{
"-6966728454894457236": "50"
},
{
"-7670177853018881196": "50"
},
{
"-5753132289681546447": "50"
},
{
"-7607424647216651656": "50"
},
{
"-6860348792160569972": "50"
},
{
"-7081692058360204084": "50"
},
{
"-4284841470230159060": "50"
},
{
"-7050130964435971895": "50"
},
{
"-5460635829467019773": "50"
},
{
"-7486065564917180528": "50"
},
{
"-4775647028251006118": "50"
},
{
"-7438712711008287507": "50"
},
{
"-6655259811991911369": "50"
},
{
"-8414061350601269280": "50"
},
{
"-4138667890938143127": "50"
},
{
"-7428739044579099070": "50"
},
{
"-5783820100141303990": "50"
},
{
"-7104520570549970103": "50"
},
{
"-5351128558805225544": "50"
},
{
"-3919387380195528267": "50"
},
{
"-3924714660733547258": "50"
},
{
"-4056394674602078332": "50"
},
{
"-4062831157333201368": "50"
},
{
"-4812848481660416581": "50"
},
{
"-6513421419955124633": "50"
},
{
"-7028635231904837853": "50"
}
],
"error_info": [],
"trace_info": {}
}
],
"error_info": []
}