数仓数据预处理整体流程

数仓数据预处理整体流程

整体点的思路:(精简版).创建spark环境
二.加载当日的app埋点数据
三.解析json为rdd[AppLogBesn],
	1.解析json数据,解析成扁平格式化
	2.抽取有用字段
	3.清洗过滤不符合规则的数据
	4.构造一个case calss对象,装入数据
四.将解析好的数据进行清洗.过滤.拼接,.数据集成
	1.先将geo字段个ibmap字典收集到Driver端并广播
2.现根据收据解析后的数据取出经纬度,调用geohash算法转成geohash编码,去geo字典中进行对比查找,填充省市区
3.查找idmap字典填充guid,过滤掉guid不存在的用户
六.将结果返回parquet格式进行保存.

创建一个spark环境

加载App埋点数据

解析json

抽取json的各个字段
	在整个数据中其他的字段都是写死的,只有event(事件)这一个字段是活的,因为有的人只是浏览了网页,有的人却下单,购买,邮寄了,
	每个人都不一样所以事件不能写死,
	最好的办法就是用Map类型将所有点的事件包含进去,是(k,v)形式的其中(k就是event,v就是所有的事件本身)
	数据类型主要有String,Map,Double,类型
将时间戳改成Long格式
进行数据清洗  
	将日志中uid|imei|uuid|mac|androidId|全部为空的数据过滤掉因为全部为空整理出来没有意义
		val sb = new StringBuilder//创建一个将数据列名放在一起判断的条件
		val flagFields =sb.append(uid).append(imei).append(uuid).append(mac).append(androidId).toString().replaceAll("null,")
	将日志中cvent|eventid|sessionid缺少任一列的数据过滤掉
	
		//定义一个bean的AppLogBean(标准类)
		同时在beans文件夹下建立一个case class AppLogBean(所有的 列名:列名对应的属性)

返回结果:如果数据符合要求,则返回一个AppLogBean,如果不符合要求就返回null

		var bean:AppLogBean = null
		//&&是并且的意思.只有event为map类型map类型可以识别!=null.其余都为String.String类型判断不为空就必要要用到StringUtils.isNotBlank(列名)这种办法
		if(StringUtils.isNotBlank(flagFields)&&event!=null && StringUtils.isNotBlank(event)&& StringUtils.isNotBlank(sessionid)){
		//如果数据符合要求,则返回一个AppLogBean,如果不符合要求就返回null
		AppLogBean(所有的列名)//要与case中的定义完全吻合除非case class中有  var 列名:属性="未知"  就可以不用填
		}
		这个if结束之后返回一个bean,然后从解析json到返回bean之间的代码try{}catch{case e :Exception => null}
		//保留不为空的内容

下面已经将两个字典解析好了就剩下数据集成了 数据集成–省市区

		.map(bean =>{
		//从广播里面将地理字典取出
		val geoDict =bc_geo.value
		
		//将表格中的经度和纬度返回值,当成参数装到这个算法中(lat,lng,5)返回一个geo然后再将给传入到这个字典中!
		val lng = bean.longtitude
		val lat = bean.latitude
		//查字典 GeoHash是一个工具,geoHashStringWithCharacterPrecision就是一个方法,
		//用这个工具加这个方法传入参数就能把这个表中的经纬度,变成字典中的对应点的索引的 K
		val geo = GeoHash.geoHashStringWithCharacterPrecision(lat,lng,5)
		//当字典Get出来的类型是option,查询时如果为空就报异常了
		val maybetuple :=geoDict.get(geo)
		//所以要做个if判断
		if(maybetuple.isDefined){
		val area :(省,市,区)=maybetuple.get
		
		
		//字典中的值对应上你的表中你假设"未知"的值
		bean.province = area._1
		bean.city = area._2
		bean.district = area._3
		}
		})

下面已经将两个字典解析好了就剩下数据集成了 数据集成–guid

	val ids = Array(bean.imei,bean.imsi,bean.mac,bean.uid,bean.androidId,bean.uuid)
    var find = false
    for (elem <- ids if !find) {
      val maybeLong = idmpDict.get(elem.hashCode.toLong)
      if(maybeLong.isDefined){
        bean.guid = maybeLong.get
        find = true
      }
    }
    bean
	//最后将得到的数据表格遍历  整个框架完成!!!
	.filter(bean=> (bean.guid!=Long.MinValue))
	.toDF()

过滤掉不符合要求的数据

		.filter(_!=null)//括号里面的数据是要留下来的数据标准(filter()保留器!)
	将日志中脏数据过滤掉
	
	这个时候.todf已经可以遍历出来了,但是两个字段看不懂一个是经纬度,
	一个是全局的唯一标识
	接下来就是将这两个看不懂的字段查字典,翻译成通俗易懂的表格

数据解析成map–省市区

加载geo地理位置字典,并收集到driver端,然后广播出去
//读取
spark.read.parquet("字典所在的路径")
//收集称为一个HashMap方便以后的查询
加载guid地理位置字典,并收集到driver端,然后广播出去
收集为HashMap格式首先要搞成map (k,v)格式
.rdd
.map({
case Row(geo:String,province:String,city:String,district:String)
=>
(geo,(province,city,district))
}).collectAsMap()
val bc_geo = spark.sparkContext.broadcast(字典名)

数据解析成map–guid映射字典

加载映射字典,收集到driver端,然后广播出去
spark.read.parquet(guid的路径)
.rdd
.map ({
case Reward(bioshi_hashcode,guid)
=>
(guid,(biaoshi_hashcode,guid ))
}).collectAsMap()
val bc_idmp =spark.sparkContext.broadcast(字典名)

数据写出

关流

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值