博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用HGraphDB进行二度好友推荐
阅读量:6824 次
发布时间:2019-06-26

本文共 4161 字,大约阅读时间需要 13 分钟。

业务场景

某社交软件,需要基于用户的好友关系向用户做二度人脉的推荐。

系统中保存的关系有两种,一种是A用户的通讯录中保存了B用户的电话号码,另一种是A用户在app上面关注了B用户。
以下图所示的关系为例:
graph_example

张三和王五,李四,赵六是好友,我们需要向张三推荐孙八、杨九和钱七。

购买HGraphDB服务

在这个例子中,我们使用HGraphDB来实现二度好友推荐的需求。HGaphDB是阿里云HBase产品提供的图存储引擎,基于Apache Tinkerpop栈构建,并使用Gremlin语言进行遍历,更新和查询。HGaphDB图数据库适用于存储、管理、查询复杂并且高度连接的数据,图库的结构特别适合发现大数据集下数据之间的共性和特性,特别善于释放蕴含在数据关系之间的巨大价值。HGaphDB引擎本身并不额外收费,仅收取云hbase费用。

可以参考完成实例的购买。

建模

人脉关系是一种典型的图数据结构,而且图可以很方便的进行二度关系的查询,我们可以使用图数据库来实现这个需求。我们把每个用户作为一个顶点,用户之间的关系作为边。

作为一个例子,我们使用Gremlin Console来完成对上述关系的建模,以及示例图的录入。Gremlin Console的安装和配置参见。

按照文档安装并配置好Gremlin Console之后,我们使用如下语句连接到HGraphDB,创建一个新的图:

:remote connect tinkerpop.server conf/remote.yaml session:remote consolegraph = HBaseGraph.open("recommendation","master1-1")g = graph.traversal()

建立schema:

graph.createLabel(ElementType.VERTEX, "user", ValueType.STRING, "name", ValueType.STRING,"tel", ValueType.STRING)graph.createLabel(ElementType.EDGE, "tel_relation", ValueType.STRING);graph.createLabel(ElementType.EDGE, "follow_relation", ValueType.STRING);graph.connectLabels("user", "tel_relation", "user")graph.connectLabels("user", "follow_relation", "user")

录入示例图的数据:

zhangsan = g.addV('user').property(T.id, 'user3').property('name','zhangsan').property('tel','13012345673').next()lisi = g.addV('user').property(T.id, 'user4').property('name','lisi').property('tel','13012345674').next()wangwu = g.addV('user').property(T.id, 'user5').property('name','wangwu').property('tel','13012345675').next()zhaoliu = g.addV('user').property(T.id, 'user6').property('name','zhaoliu').property('tel','13012345676').next()qianqi = g.addV('user').property(T.id, 'user7').property('name','qianqi').property('tel','13012345677').next()sunba = g.addV('user').property(T.id, 'user8').property('name','sunba').property('tel','13012345678').next()yangjiu = g.addV('user').property(T.id, 'user9').property('name','yangjiu').property('tel','13012345679').next()zhangsan.addEdge('tel_relation',lisi)lisi.addEdge('tel_relation',zhangsan)zhangsan.addEdge('tel_relation',zhaoliu)zhaoliu.addEdge('tel_relation',zhangsan)lisi.addEdge('tel_relation',zhaoliu)zhaoliu.addEdge('tel_relation',lisi)lisi.addEdge('tel_relation',qianqi)qianqi.addEdge('tel_relation',lisi)zhangsan.addEdge('follow_relation',wangwu)wangwu.addEdge('tel_relation',sunba)wangwu.addEdge('follow_relation',yangjiu)

更新

作为一个例子,上面的语句里面,我们一次性把图构建完成了。在生产当中更常见到的情况是,随着系统的运行不断有新用户注册,我们需要更新这个图。例如一个场景是新用户陈十注册,我们通过匹配通讯录发现陈十留过李四的手机号。

为了加快通过手机查用户,我们需要给手机号字段加一个索引:

graph.createIndex(ElementType.VERTEX, "user", "tel",true)

如下语句完成了新用户陈十的注册过程:

chenshi = g.addV('user').property(T.id, 'user10').property('name','chenshi').property('tel','13012345680').next()lisi = g.V().has("tel","13012345674").next()chenshi.addEdge('tel_relation',lisi)

陈十关注了王五、赵六:

wangwu = g.V("user5").next()zhaoliu = g.V("user6").next()chenshi.addEdge('follow_relation',wangwu)chenshi.addEdge('follow_relation',zhaoliu)

陈十取关赵六:

g.V('user10').outE('follow_relation').as('e').inV().hasId('user6').select('e').drop()

陈十注销账号:

g.V("user10").drop()

这里通过drop删除顶点后,相应的边也会自动删除。

查询

我们可以用一个简单的语句进行二度人脉的查询:

gremlin> g.V("user3").out().out().valueMap()==>{name=[yangjiu], tel=[13012345679]}==>{name=[sunba], tel=[13012345678]}==>{name=[zhangsan], tel=[13012345673]}==>{name=[zhangsan], tel=[13012345673]}==>{name=[zhaoliu], tel=[13012345676]}==>{name=[qianqi], tel=[13012345677]}==>{name=[lisi], tel=[13012345674]}

但是这个语句很粗糙,返回的结果里面既有张三自己,也有张三已经认识了的李四、赵六。我们需要过滤掉这些不需要推荐的人:

gremlin> g.V("user3").as('self').out().aggregate('friend').out().where(neq('self')).where(without('friend')).valueMap().dedup()==>{name=[yangjiu], tel=[13012345679]}==>{name=[sunba], tel=[13012345678]}==>{name=[qianqi], tel=[13012345677]}

gremlin查询功能是很强大的,例如我们也可以只给张三推荐他关注的人的好友:

gremlin> g.V("user3").as('self').out("follow_relation").aggregate('friend').out().where(neq('self')).where(without('friend')).valueMap().dedup()==>{name=[yangjiu], tel=[13012345679]}==>{name=[sunba], tel=[13012345678]}

判断两个人是不是好友:

gremlin> g.V("user3").outE().as("e").inV().hasId("user4").select("e")==>e[0e4e63a3-638a-4dd9-8087-59e819896576][user3-tel_relation->user4]

有没有关注过:

gremlin> g.V("user3").outE("follow_relation").as("e").inV().hasId("user4").select("e")gremlin>

转载地址:http://uzgzl.baihongyu.com/

你可能感兴趣的文章
数据操作与查询语句
查看>>
selenium webdriver (11) -- 截图
查看>>
sublime插件安装
查看>>
网络配置多会话实验
查看>>
如何挑选适合自己的HTML5视频课程
查看>>
windows提权
查看>>
苹果Siri再新增服务内容 航班查询、餐点外送和血糖监控
查看>>
学习笔记
查看>>
远程协助,TeamViewer之外的另一种选择
查看>>
Centos 6.5 部署 LNMP
查看>>
网安天目
查看>>
rsync远程同步及rsync+inotify实时同步
查看>>
Redis分布式锁的正确实现方式(Java版)
查看>>
Linux20180427
查看>>
linux系统配置及服务管理第一章系统部署
查看>>
SQL语句优化:show参数
查看>>
webstorm那些常用快捷键
查看>>
MySQL5.7 group by新特性报错1055的解决办法
查看>>
网易企业邮箱的萨班斯归档是什么?
查看>>
阿里架构师告诉你最新Java架构师学习路线图
查看>>