抽取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()