“这就是我,一个低调的作者。”
在上一篇文章,我们讲解了使用hive处理简单“品类隔断”的技巧,但是在文章结尾,我们的产品经理,要求做一款升级版的“品类隔断”。具体的需求内容,请翻看《如何利用hive技巧实现简单的“品类隔断”(一)》,这里不再赘述,我们直接看解题思路。 ##解题思路 产品经理要求我们给用户10001展示考虑带有偏好强弱因素在内的顺序,即上一篇文章提到的:用户对每个分类的偏好的强弱决定了对应分类的商品展示的个数: 例如用户10001的展示顺序为:
衣服,衣服,衣服,鞋子,鞋子,手机,衣服,衣服,衣服,鞋子,鞋子,手机…
从而体现出了用户偏好强弱,而不至于出现上述不同偏好但同等概率展示的情况。 那么如何做呢,开始揭晓答案~ 用户10001的偏好召回表如下: userId(用户id)|cate(分类)|prefer(用户对该分类的偏好)|pids(该分类下已经排好序的商品id集合,以,分隔) —|—|—|— 10001|鞋子|10.9|P10003,P10001,P10010 10001|衣服|12.4|P10002,P10004,P10008,p10024,p10035 10001|手机|0.3|P10007,P10005,P1006,P10025 而我们给用户线上展示的结果顺序如下:
P10002(衣服), P10004(衣服), P10008(衣服), P10003(鞋子), P10001(鞋子), P10007(手机), P10024(衣服), P10035(衣服), P10010(鞋子), P10005(手机)
可以看出,我们先给用户在衣服这个最强偏好曝光3个商品,然后在鞋子这个偏好曝光2个商品,最后在手机这个偏好曝光1个商品,以此类推… 这里的难点在于我们如何利用用户偏好的强弱,来分别取不同商品的个数。其实我们可以考虑利用偏好排序打标进行除法取整,进而进行分组聚合。 那么,我们在hive中如何实现呢,思路是这样的: #####1、 对用户10001下的分类偏好进行排序(顺排)打标
用户id 分类 偏好分 偏好排序打标 该分类下已经排好序的商品集合
10001 衣服 12.4 3 P10002,P10004,P10008,P10024,P10035
10001 鞋子 10.9 2 P10003,P10001,P10010
10001 手机 0.3 1 P10007,P10005,P10006,P10025
#####2、 对用户10001下的分类偏好下的商品行转列,并对其做排序打标
用户id 分类 偏好分 偏好排序打标 商品id 商品排序
10001 衣服 12.4 3 P10002 1
10001 衣服 12.4 3 P10004 2
10001 衣服 12.4 3 P10008 3
10001 衣服 12.4 3 P10024 4
10001 衣服 12.4 3 P10035 5
10001 鞋子 10.9 2 P10003 1
10001 鞋子 10.9 2 P10001 2
10001 鞋子 10.9 2 P10010 3
10001 手机 0.3 1 P10007 1
10001 手机 0.3 1 P10005 2
10001 手机 0.3 1 P10006 3
10001 手机 0.3 1 P10025 4
#####3、 利用商品排序对偏好排序除法取整,实现不同偏好对应取到的商品个数
用户id 分类 偏好分 偏好排序打标 商品id 商品排序 聚合标记
10001 衣服 12.4 3 P10002 1 (1-1)/3=0
10001 衣服 12.4 3 P10004 2 (2-1)/3=0
10001 衣服 12.4 3 P10008 3 (3-1)/3=0
10001 衣服 12.4 3 P10024 4 (4-1)/3=1
10001 衣服 12.4 3 P10035 5 (5-1)/3=1
10001 鞋子 10.9 2 P10003 1 (1-1)/2=0
10001 鞋子 10.9 2 P10001 2 (2-1)/2=0
10001 鞋子 10.9 2 P10010 3 (3-1)/2=1
10001 手机 0.3 1 P10007 1 (1-1)/1=0
10001 手机 0.3 1 P10005 2 (2-1)/1=1
10001 手机 0.3 1 P10006 3 (3-1)/1=2
10001 手机 0.3 1 P10025 4 (4-1)/1=3
#####4、 按照偏好排序打标和聚合标记进行商品重组
用户id 偏好排序打标 聚合标记 商品重组结果
10001 3 0 P10002, P10004, P10008
10001 3 1 P10024, P10035
10001 2 0 P10003, P10001
10001 2 1 P10010
10001 1 0 P10007
10001 1 1 P10005
10001 1 2 P10006
10001 1 3 P10025
#####5、 按照聚合标记进行商品分组聚合
用户id 聚合标记 商品分组聚合结果
10001 0 P10002, P10004, P10008, P10003, P10001, P10007
10001 1 P10024, P10035, P10010, P10005
10001 2 P10006
10001 3 P10025
#####6、 按照用户最终聚合商品排序展示顺序
用户id 最终展示结果顺序
10001 P10002, P10004, P10008, P10003, P10001, P10007, P10024, P10035, P10010, P10005, P10006, P10025
这样就达到了产品经理对于“品类隔断”升级版需求的要求了,以下给出hive sql供大家参考:
select
userId,
concat_ws(',', collect_list(pids_2)) as final_pids
from
(
select
userId,
agg_flag,
concat_ws(',', collect_list(pids_1)) as pids_2
from
(
select
userId,
rk_prefer,
agg_flag,
concat_ws(',', collect_list(pid)) as pids_1
from
(
select
userId,
cate,
prefer,
rk_prefer,
pid,
rk_pid,
cast((rk_pid - 1) / rk_prefer as int) as agg_flag
from
(
select
userId,
cate,
prefer,
rk_prefer,
pid,
row_number() over(partition by userId, rk_prefer) as rk_pid
from
(
select
userId,
cate,
prefer,
rk_prefer,
pids
from
(
select
userId,
cate,
prefer,
row_number() over(partition by userId order by prefer asc) as rk_prefer
pids
from
tbl_user_prefer_recall
) tbl_1
distribute by userId
order by rk_prefer desc
) tbl_2
lateral view explode(split(pids, ',')) as tbl_tmp as pid
) tbl_3
) tbl_4
group by userId,
rk_prefer,
agg_flag
) tbl_5
group by userId,
agg_flag
) tbl_6
group by userId;
##总结 到此,“品类隔断”升级版需求讲解完毕,你学会了吗?
#注:纯手工打造,实属不易,欢迎大家分享和转发~ #原创内容,转载需注明出处,否则视为侵权并将被追诉!