如何利用hive技巧实现简单的“品类隔断”(二)

Posted by Mrchor on May 18, 2020

“这就是我,一个低调的作者。”

在上一篇文章,我们讲解了使用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;

##总结 到此,“品类隔断”升级版需求讲解完毕,你学会了吗?

#注:纯手工打造,实属不易,欢迎大家分享和转发~ #原创内容,转载需注明出处,否则视为侵权并将被追诉!