一、环境要求
Hadoop+Hive+Spark+HBase 开发环境。
二、提交结果要求
1.必须提交源码或对应分析语句,如不提交则不得分。
2.带有分析结果的功能,请分析结果的截图与代码一同提交。
三、数据描述
文件下载地址
链接:https://pan.baidu.com/s/1leER9nB_TUnrK5Kk4EHZ1w
提取码:1234
meituan_waimai_meishi.csv 是美团外卖平台的部分外卖 SPU(Standard Product Unit ,
标准产品单元)数据,包含了外卖平台某地区一时间的外卖信息。具体字段说明如下:
四、功能要求
1.数据准备(10 分)
请在 HDFS 中创建目录/app/data/exam,并将 meituan_waimai_meishi.csv 文件传到该
目录。并通过 HDFS 命令查询出文档有多少行数据。
hdfs dfs -mkdir -p /app/data/exam
hdfs dfs -put meituan_waimai_meishi.csv /app/data/exam
hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l
2.使用 Spark,加载 HDFS 文件系统 meituan_waimai_meishi.csv 文件,并分别使用 RDD
和 Spark SQL 完成以下分析(不用考虑数据去重)。(50 分)
RDD
①统计每个店铺分别有多少商品(SPU)。
val fileRDD = sc.textFile("hdfs://cm:9000/app/data/exam/meituan_waimai_meishi.csv")
val spuRDD = fileRDD.filter(x=>x.startsWith("spu_id")==false).map(x=>x.split(",",-1)).filter(x=>x.size==12)
spuRDD.map(x=>(x(2),1)).reduceByKey(_+_).collect.foreach(println)
②统计每个店铺的总销售额。
import scala.util._
spuRDD.map(x=>(x(2),Try(x(5).toDouble).toOption.getOrElse(0.0)* Try(x(7).toInt).toOption.getOrElse(0))).reduceByKey(_+_).collect.foreach(println)
③统计每个店铺销售额最高的前三个商品,输出内容包括店铺名,商品名和销售额,其
中销售额为 0 的商品不进行统计计算,例如:如果某个店铺销售为 0,则不进行统计。
spuRDD.map(x=>(x(2),x(4),Try(x(5).toDouble).toOption.getOrElse(0.0)* Try(x(7).toInt).toOption.getOrElse(0))).filter(x=>x._3>0).groupBy(_._1).map(x=>{val shop_name=x._1; val three=x._2.toList.sortBy(it=>(-1*it._3)).take(3).map(x=>(x._2,x._3));(shop_name,three)}).collect.foreach(println)
Spark SQL
①统计每个店铺分别有多少商品(SPU)。
//自动转换格式option(“inferSchema”,“true”),手动转换见尾页
import spark.implicits._
import org.apache.spark.sql._
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._
val spuDF = spark.read.format("csv").option("header","true").option("inferSchema","true").load("hdfs://cm:9000/app/data/exam/meituan_waimai_meishi.csv")
spuDF.createOrReplaceTempView("spu")
spark.sql("select shop_name,count(1) as num from spu group by shop_name").show()
②统计每个店铺的总销售额。
spark.sql("select shop_name,sum(spu_price*month_sales) as money from spu group by shop_name").show()
③统计每个店铺销售额最高的前三个商品,输出内容包括店铺名,商品名和销售额,其
中销售额为 0 的商品不进行统计计算,例如:如果某个店铺销售为 0,则不进行统计。
spark.sql("select t.shop_name,t.spu_name,t.money from (select shop_name,spu_name,(spu_price*month_sales) as money,row_number() over(partition by shop_name order by spu_price*month_sales desc) as rn from spu where month_sales>0) t where rn<4 ").show()
3.创建HBase数据表(5分)
在HBase中创建命名空间(namespace)exam,在该命名空间下创建spu表,该表下有1个列族result。
create_namespace 'exam'
create 'exam:spu','result'
4.请在Hive 中创建数据库spu_db,在该数据库中创建外部表ex_spu指向/app/data/exam下的测试数据;创建外部表ex_spu_hbase映射至HBase中的exam:spu表的result列族(20分)
create external table if not exists ex_spu(
spu_id string,
shop_id string,
shop_name string ,
category_name string ,
spu_name string ,
spu_price double ,
spu_originprice double ,
month_sales int ,
praise_num int ,
spu_unit string ,
spu_desc string ,
spu_image string )
row format delimited
fields terminated by ','
stored as textfile
location '/app/data/exam'
tblproperties("skip.header.line.count"="1");
create external table if not exists ex_spu_hbase(
key string,
sales double,
praise int
)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties
("hbase.columns.mapping"=":key,result:sales,result:praise")
tblproperties("hbase.table.name"="exam:spu");
5.统计查询(15分)
①统计每个店铺的总销售额sales, 店铺的商品总点赞数praise,并将shop_id和shop_name的组合作为RowKey,并将结果映射到HBase。
insert into ex_spu_hbase select concat(t.shop_id,t.shop_name),t.sales,t.praise from (select shop_id,shop_name,sum(spu_price*month_sales)as sales,sum(praise_num) as praise from ex_spu group by shop_id,shop_name) t;
②完成统计后,分别在hive和HBase中查询结果数据。
select * from ex_spu_hbase;
scan 'exam:spu'
拓展
RDD转换DataFrame
scala> val spuRowRDD = fileRDD.filter(x=>x.startsWith("spu_id")==false).map(x=>x.split(",",-1)).filter(x=>x.size==12).map(p=>Row(p(1),p(2),p(4),Try(p(5).toDouble).toOption.getOrElse(0.0),Try(p(7).toInt).toOption.getOrElse(0)))
scala> val spuSchema = StructType(
| Array(
| StructField("shop_id",StringType,true),
| StructField("shop_name",StringType,true),
| StructField("spu_name",StringType,true),
| StructField("spu_price",DoubleType,true),
| StructField("month_sales",IntegerType,true)
| )
| )
scala> val spuDF2 = spark.createDataFrame(spuRowRDD,spuSchema)
DataFrame手动转换
scala> val spuDF: DataFrame = spark.read.format("csv").option("header","true").load("hdfs://cm:9000/app/data/exam/meituan_waimai_meishi.csv")
scala> spuDF.printSchema
scala> spuDF.withColumn("spu_price",$"spu_price".cast(DataTypes.DoubleType)).printSchema