综合案例 第80课:Spark SQL网站搜索综合案例实战 以京东找出搜索平台上用户每天搜索排名5名的产品,The hottest!

* * *王家林老师授课http://weibo.com/ilovepains */  每天晚上20:00YY频道现场授课频道68917580

 

/**

 *@author DT大数据梦工厂

 * 新浪微博:http://weibo.com/ilovepains/

 *Created by hp on 2016/4/1.

 *      项目:以京东找出搜索平台上用户每天搜索排名5名的产品,Thehottest

 *     元数据:DateUserIDItemCityDevice

 *     总体思路:混合使用了Spark SQLSpark Core的内容

 *     第一步:原始的ETL,过滤数据后产生目标,在实际企业中可能过滤条件非常复杂(进行广播),使用RDDfilter等进行操作;

 *     第二步:对过滤后的目标数据进行指定条件的查询,查询条件有可能非常复杂(进行广播),使用RDDfilter算子;

 *     第三步:由于商品是分为种类的,我们在得出最终结果的之前,首先会基于商品进行UV(当然你也可以对用户访问商品的PV进行分析);

 *      此时我们要对商品进行UV计算的话,必须构建K-VRDD,例如过程成为 (date#Item,userID)以方便进行groupByKey操作

 *      在调用了groupByKey之后对user进行去重,并计算出每一天每一种商品的UV,最终计算出来的结果的数据类型(date#Item,UV)

 *     第四步:使用开窗函数row_number统计出每日商品UV5名的内容,

 *  row_number() OVER (PARTITION BY date ORDER BY UV DESC) rank   

 *      此时会产生以dateitemuvRowDataFrame

 *     第五步:DataFrame转成RDD,根据日期进行分组并分析出每天排名前5为的热搜索Item

 *     第六步:进行Key-Value交换,然后进行调用sortByKey进行点击热度排名;

 *     第七步:再次进行Key-Value交换,得出目标数据为(date#Item,UV)的格式;

 *     第八步:通过RDD直接操作Mysql等把结果放入生产系统中的DB中,在通过Java EEServer技术可视化结果以供市场

 *      营销人员、仓库调度系统、快递系统、管理决策人员使用数据创造价值;

 *      当然也可以放在Hive中,Java EE等技术通过JDBC等连接访问Hive

 *      当然也可以就放在Spark SQL中,通过Thrift技术供Jave EE使用等;

 *      当时,如果是像双十一等时候,一般首选放在Redis中,这样可以实现类似秒杀系统的响应速度!

 */

 

 

综合案例 第80课:Spark SQL网站搜索综合案例实战 以京东找出搜索平台上用户每天搜索排名5名的产品,The hottest!_第1张图片

 

综合案例 第80课:Spark SQL网站搜索综合案例实战 以京东找出搜索平台上用户每天搜索排名5名的产品,The hottest!_第2张图片

 

 

 

运行结果!

 

 

 综合案例 第80课:Spark SQL网站搜索综合案例实战 以京东找出搜索平台上用户每天搜索排名5名的产品,The hottest!_第3张图片

 

 

 综合作业 第80课Spark SQL网站搜索综合案例实战
以京东为例找出搜索平台上用户每天搜索排名5名的产品,The hottest!
  用户登录京东网站,在搜索栏搜索的时候,将用户每天搜索排名前5名的商品列出来。
 
 
一:生成模拟京东用户搜索的测试数据。
 SparkSQLUserlogsHottest.log测试数据文件包括时间、用户id、商品、地点、设备信息 10000条数据
 
二:根据测试数据实现搜索平台上用户每天搜索排名5名的产品。
 创建JavaSparkContext及HiveContext
 sc.textFile读入测试数据文件,生成JavaRDD类型的数据集合line0。
 sc.broadcast定义广播变量,用于测试数据的查询及过滤。
 lines0.filter使用匿名接口函数Function的call方法过滤出包含广播变量的数据,生成JavaRDD 类型的数据集合lines。
 测试验证点:
测试数据广播变量的过滤是否成功?打印出lines的数据验证。
 
 lines.mapToPair 使用匿名接口函数PairFunction的call方法对lines中的数据按"\t"进行分割,分割以后将(date#Item#userID)三个字段合并为Key, 将 Value值设置为1,形成   K,V键值对。返回的结果pairs类型为JavaPairRDD。相当于hadoop mapreduce中的map,将某天某用户点击某商品的次数计数为1。
 测试验证点:
测试(date#Item#userID)三个字段合并为Key成功了吗?k,v是否符合预期?
 
 pairs.reduceByKey使用匿名接口函数Function2的call方法对pairs中数据进行reduce汇总,将pairs具有相同key值的数据,累加统计数值,返回的结果reduceedPairs 的类型为JavaPairRDD。相当于hadoop mapreduce中的reduce,将某天某用户点击某商品的所有点击次数累加汇总。
 测试验证点:
测试(date#Item#userID) k,v的reduce统计是否成功?
将reduceedRow中的每行数据拆分,reduceedRow的key值分割为三个字段:时间、用户id、商品,将reduceedRow的商品累计点击数值value记为count,然后将这四个字段时间、用户id、商品、count再拼接成json格式放到peopleInformations列表里面,打印输出。peopleInformations类型为List,为json格式。
 
 sc.parallelize(peopleInformations)将scala空间的变量peopleInformations转换为Spark RDD空间的变量peopleInformationsRDD,类型为JavaRDD
 sqlContext.read().json(peopleInformationsRDD)通过内容为JSON的RDD来构造peopleInformationsDF,类型为DataFrame
 DataFrame注册成为临时表
peopleInformationsDF.registerTempTable("peopleInformations")
 窗口函数:使用子查询的方式完成目标数据的提取,在目标数据内幕使用窗口函数row_number来进行分组排序, PARTITION BY :指定窗口函数分组的Key, ORDER BY:分组后进行排序;
        String sqlText = "SELECT UserID,Item, count "
           + "FROM ("
             + "SELECT "
             + "UserID,Item, count,"
           + "row_number() OVER (PARTITION BY UserID ORDER BY count DESC) rank"
               +" FROM peopleInformations "
           + ") sub_peopleInformations "
           + "WHERE rank <= 3 " ;
   Sql查询语句:
 使用窗口函数,查询peopleInformations表,按照用户分组,将同一用户的每天的点击的商品数排名,形成一张子表sub_peopleInformations。
 然后从排名后的子表sub_peopleInformations中,查询出前三名的用户点击的商品和计数。
 测试验证点:
验证窗口函数sql语句执行是否成功?
sqlContext.sql(sqlText)执行sql查询,execellentNameAgeDF.show()显示sql查询结果。
 
 将execellentNameAgeDF的结果保存为json文件格式
execellentNameAgeDF.write().format("json").save();
三:源代码SparkSQLUserlogsHottestDataManually.java和SparkSQLUserlogsHottest.java

 

 

 

packagecom.dt.imf.zuoye001;

 

importjava.util.ArrayList;

importjava.util.Arrays;

importjava.util.Iterator;

importjava.util.List;

 

importorg.apache.hadoop.hive.ql.parse.HiveParser_IdentifiersParser.function_return;

importorg.apache.hadoop.io.IntWritable;

importorg.apache.spark.SparkConf;

importorg.apache.spark.api.java.JavaPairRDD;

importorg.apache.spark.api.java.JavaRDD;

importorg.apache.spark.api.java.JavaSparkContext;

importorg.apache.spark.api.java.function.Function;

importorg.apache.spark.api.java.function.Function2;

importorg.apache.spark.api.java.function.PairFunction;

importorg.apache.spark.api.java.function.VoidFunction;

importorg.apache.spark.broadcast.Broadcast;

importorg.apache.spark.sql.DataFrame;

importorg.apache.spark.sql.Row;

importorg.apache.spark.sql.RowFactory;

importorg.apache.spark.sql.SQLContext;

importorg.apache.spark.sql.types.DataTypes;

importorg.apache.spark.sql.types.StructField;

importorg.apache.spark.sql.types.StructType;

importorg.apache.spark.sql.hive.HiveContext;

 

import scala.Tuple2;

 

public classSparkSQLUserlogsHottest {

 

       public static void main(String[] args) {

              SparkConf conf = newSparkConf().setMaster("local").setAppName("SparkSQLUserlogsHottest");

              JavaSparkContext sc = newJavaSparkContext(conf);

              SQLContext sqlContext = newHiveContext(sc);

 

              JavaRDD lines0 =sc.textFile("G:\\IMFBigDataSpark2016\\tesdata\\SparkSQLUserlogsHottest\\SparkSQLUserlogsHottest.test.log");

               

              /*元数据:Date、UserID、Item、City、Device;

          (date#Item#userID)

              */

                           

              //定义广播变量

               String  devicebd="iphone";

               final Broadcast  broadcastdevice =sc.broadcast(devicebd);  

              // 过滤

             

              // lines.filter();

               JavaRDD lines =lines0.filter(new Function() {

                    

                     @Override

                     public Boolean call(Strings) throws Exception {

                            returns.contains(broadcastdevice.value());

                     }

              });

               

               // 验证

               List  listRow000 =lines.collect();

                                   for(  String row : listRow000){

                                          System.out.println(row);

                                   }

     

               

               //组拼字符串(date#Item#userID)  构建KV(date#Item#userID,1)

               JavaPairRDD pairs =lines.mapToPair(new PairFunction() {

                      private static final longserialVersionUID =1L ;               

                      @Override                            

                            publicTuple2 call(String line) throws Exception {

                                   String[]splitedLine =line.split("\t");

                             int one = 1;

                                   Stringdataanditemanduserid = splitedLine[0] +"#"+splitedLine[2]+"#"+String.valueOf(splitedLine[1]);

                                   return newTuple2(String.valueOf(dataanditemanduserid),Integer.valueOf(one));

                                  

                            }

                     });

               

               //  验证

                 List> listRow = pairs.collect();

                                   for(Tuple2row : listRow){

                                          System.out.println(row._1);

                                          System.out.println(row._2);

                                   }

       

                               

                      //reducebykey,统计计数

                                  

             JavaPairRDD reduceedPairs =pairs.reduceByKey(new Function2() {

                    

                     @Override

                     public Integer call(Integerv1, Integer v2) throws Exception {

                            return v1 + v2 ;

                     }

              });

                                       

                               

             List>  reduceedRow = reduceedPairs.collect();

             

              //动态组拼出JSON

                     ListpeopleInformations = new ArrayList();

                    

                    

                     for(Tuple2row : reduceedRow){

                            //拆分三个字段

                         String[] rowSplitedLine=row._1.split("#");

                            String rowuserID =rowSplitedLine[2];

                            String rowitemID =rowSplitedLine[1];

                            String rowdateID =rowSplitedLine[0];

                    

                     //拼接json  元数据:Date、UserID、Item、City、Device      

                            String jsonzip=     "{\"Date\":\""+rowdateID 

                                         +"\",\"UserID\":\""+ rowuserID 

                                         +"\",\"Username\":\""+ rowuserID

                                         +"\",\"Item\":\""+ rowitemID 

                                         +"\",\"count\":"+ row._2 +" }";

                        peopleInformations.add(jsonzip);

                           

                     }     

                                     

                     //打印验证peopleInformations

                                 

                     for(String row :peopleInformations){

                            System.out.println(row.toString());

                            //System.out.println(row._2);

                     }

                    

                     //通过内容为JSON的RDD来构造DataFrame

                     JavaRDDpeopleInformationsRDD = sc.parallelize(peopleInformations);

                     DataFramepeopleInformationsDF = sqlContext.read().json(peopleInformationsRDD);

                    

                     //注册成为临时表

                     peopleInformationsDF.registerTempTable("peopleInformations");

                           

                    

                       /* 使用子查询的方式完成目标数据的提取,在目标数据内幕使用窗口函数row_number来进行分组排序:

                    * PARTITION BY :指定窗口函数分组的Key;

                    * ORDER BY:分组后进行排序;

                    */

               

        String sqlText = "SELECTUserID,Item, count "

                       + "FROM ("

                         + "SELECT "

                           + "UserID,Item, count,"

                           + "row_number() OVER(PARTITION BY UserID ORDER BY count DESC) rank"

                           +" FROM peopleInformations"

                       + ") sub_peopleInformations"

                       + "WHERE rank <= 3 " ;

      

      

           

                     DataFrameexecellentNameAgeDF = sqlContext.sql(sqlText);

                     execellentNameAgeDF.show();

              execellentNameAgeDF.write().format("json").save("G:\\IMFBigDataSpark2016\\tesdata\\SparkSQLUserlogsHottest\\Result20140419_2");

             

       }

 

}

 

 

 

你可能感兴趣的:(Hadoop)