电商用户行为分析大数据平台(四)-- top10热门品类分析

一、需求回顾
----------------------------------------------------------
    1.计算出来通过筛选条件的那些session,他们访问过的所有品类(点击、下单、支付),按照各个品类的点击、下单和支付次数,降序排序,
    获取前10个品类,也就是筛选条件下的那一批session的top10热门品类;

    2.点击、下单和支付次数:优先按照点击次数排序、如果点击次数相等,那么按照下单次数排序、如果下单次数相当,那么按照支付次数排序

    3.这个需求是很有意义的,因为这样,就可以让数据分析师、产品经理、公司高层,随时随地都可以看到自己感兴趣的那一批用户,
      最喜欢的10个品类,从而对自己公司和产品的定位有清晰的了解,并且可以更加深入的了解自己的用户,更好的调整公司战略


二、思路分析
-------------------------------------------------------
    1.拿到通过筛选条件的那批session,访问过的所有品类
    2.计算出session访问过的所有品类的点击、下单和支付次数,这里可能要跟第一步计算出来的品类进行join
    3.自己开发二次排序的key
    4.做映射,将品类的点击、下单和支付次数,封装到二次排序key中,作为PairRDD的key
    5.使用sortByKey(false),按照自定义key,进行降序二次排序
    6.使用take(10)获取,排序后的前10个品类,就是top10热门品类
    7.将top10热门品类,以及每个品类的点击、下单和支付次数,写入MySQL数据库
    8.本地测试
    9.使用Scala来开发二次排序key


三、具体步骤
-------------------------------------------------------
    1.获取符合条件的session访问过的所有品类
        a.首先拿到之前的两个RDD,
          filteredSessionid2AggrInfoRDD --> 根据taskparam过滤过后的<sessionid, fullaggrinfo>
          sessionid2actionRDD --> user_visit_action表的Row信息与sessionid的映射

        b.因为要使用按照条件过滤后的sessionid2actionRDD,所以,拿filteredSessionid2AggrInfoRDD.join(sessionid2actionRDD)
          得到<sesssionid,[fullaggrinfo,action_row]>  rdd1
          对rdd1进行mapToPair(),去掉fullaggrinfo,仅留下<sesssionid,action_row>的映射
          从而得到符合条件的session访问过的所有品类sessionid2detailRDD <sesssionid,action_row>

    2.获取符合条件的session访问过的所有品类id [访问过:指的是,点击过、下单过、支付过的品类]
        a.对sessionid2detailRDD应用flatMapToPair,得到JavaPairRDD<Long, Long> categoryidRDD
        其中的<Long,Long> 为 点击的<clickCategoryId, clickCategoryId>,<orderCategoryId,orderCategoryId>,<payCategoryId,payCategoryId>

        b.这样就得到了符合条件的session所有访问过的商品品类id(点击过,订单过,支付过),用<Long,Long>表示categoryidRDD <Long,Long>

        c.至于为什么<clickCategoryId, clickCategoryId>,是为了以后的join用

    3.计算各品类的点击、下单和支付的次数
        a.计算各个品类的点击次数
            对sessionid2detailRDD <sesssionid,action_row>应用filter,过滤掉action_row中click_category_id的字段为空的行,得到clickActionRDD
            对clickActionRDD <sesssionid,action_row>应用mapToPair,每行都变换成<clickCategoryId,1> 最终得到<clickCategoryId,1> clickCategoryIdRDD
            对<clickCategoryId,1> clickCategoryIdRDD应用reduceByKey,进行聚合,得到clickCategoryId和对应的count,JavaPairRDD<Long, Long> clickCategoryId2CountRDD

        b.计算各个品类的下单次数
            同上得到JavaPairRDD<Long, Long> orderCategoryId2CountRDD

        c.计算各个品类的支付次数
            同上得到JavaPairRDD<Long, Long> payCategoryId2CountRDD

    4.join各品类与它的点击、下单和支付的次数
        a.JavaPairRDD<Long, Tuple2<Long, Optional<Long>>> tmpJoinRDD = categoryidRDD.leftOuterJoin(clickCategoryId2CountRDD);

        b.对tmpJoinRDD进行mapToPair变换,得到<categoryId, "categoryid|clickCount"> tmpMapRDD,这样就将categoryidRDD的有点击的行,增加了点击次数

        c.同上,对上面的tmpMapRDD,进行leftOuterJoin(orderCategoryId2CountRDD),然后mapToPair变换,得到新的
        <categoryId, "categoryid|clickCount|orderCount"> tmpMapRDD

        c.同上,对上面的tmpMapRDD,进行leftOuterJoin(payCategoryId2CountRDD),然后mapToPair变换,得到新的
        <categoryId, "categoryid|clickCount|orderCount|payCount"> tmpMapRDD

        d.最终得到<categoryId, "categoryid|clickCount|orderCount|payCount"> categoryid2countRDD

    5.自定义二次排序key
        /*
        *
        * 封装你要进行排序算法需要的几个字段:点击次数、下单次数和支付次数
        * 实现Ordered接口要求的几个方法
        *
        * 跟其他key相比,如何来判定大于、大于等于、小于、小于等于
        *
        * 依次使用三个次数进行比较,如果某一个相等,那么就比较下一个
        */
        public class CategorySortKey implements Ordered<CategorySortKey> {

           private long clickCount;
           private long orderCount;
           private long payCount;

           public boolean $greater(CategorySortKey other) {
              if(clickCount > other.getClickCount()) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount > other.getOrderCount()) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount == other.getOrderCount() &&
                    payCount > other.getPayCount()) {
                 return true;
              }
              return false;
           }


           public boolean $greater$eq(CategorySortKey other) {
              if($greater(other)) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount == other.getOrderCount() &&
                    payCount == other.getPayCount()) {
                 return true;
              }
              return false;
           }


           public boolean $less(CategorySortKey other) {
              if(clickCount < other.getClickCount()) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount < other.getOrderCount()) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount == other.getOrderCount() &&
                    payCount < other.getPayCount()) {
                 return true;
              }
              return false;
           }


           public boolean $less$eq(CategorySortKey other) {
              if($less(other)) {
                 return true;
              } else if(clickCount == other.getClickCount() &&
                    orderCount == other.getOrderCount() &&
                    payCount == other.getPayCount()) {
                 return true;
              }
              return false;
           }


           public int compare(CategorySortKey other) {
              if(clickCount - other.getClickCount() != 0) {
                 return (int) (clickCount - other.getClickCount());
              } else if(orderCount - other.getOrderCount() != 0) {
                 return (int) (orderCount - other.getOrderCount());
              } else if(payCount - other.getPayCount() != 0) {
                 return (int) (payCount - other.getPayCount());
              }
              return 0;
           }


           public int compareTo(CategorySortKey other) {
              if(clickCount - other.getClickCount() != 0) {
                 return (int) (clickCount - other.getClickCount());
              } else if(orderCount - other.getOrderCount() != 0) {
                 return (int) (orderCount - other.getOrderCount());
              } else if(payCount - other.getPayCount() != 0) {
                 return (int) (payCount - other.getPayCount());
              }
              return 0;
           }

           public long getClickCount() {
              return clickCount;
           }

           public void setClickCount(long clickCount) {
              this.clickCount = clickCount;
           }

           public long getOrderCount() {
              return orderCount;
           }

           public void setOrderCount(long orderCount) {
              this.orderCount = orderCount;
           }

           public long getPayCount() {
              return payCount;
           }

           public void setPayCount(long payCount) {
              this.payCount = payCount;
           }

        }

    6.将数据映射成<sortkey,info>格式的rdd,然后进行二次排序
        a.对<categoryId, "categoryid|clickCount|orderCount|payCount"> categoryid2countRDD 应用mapToPair,
        得到<CategorySortKey,countstr>格式的RDD sortKey2countRDD

        b.JavaPairRDD<CategorySortKey, String> sortedCategoryCountRDD = sortKey2countRDD.sortByKey(false);  false表示降序

    7.用take(10)取出top10热门品类,并写入MySQL
        List<Tuple2<CategorySortKey, String>> top10CategoryList = sortedCategoryCountRDD.take(10);





猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/86516112