开发者学堂课程【2020版大数据实战项目之 DMP 广告系统(第七阶段):打标签_生成标签】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/682/detail/11836
打标签_生成标签
本节主要讲如何执行具体的打标签任务,以及如何把 Row 对象转成一个 IdsWithTags 对象
打标签环境已经准备好了,接下来可以执行具体的打标签的任务,前面的“join”。
生成标签数据的本质是把 ods 层的表或者数据集给它加上一些标签信息,拿到odsWithArea
后通过一些方式往里面添加一些列。
//(3.3) 生成标签数据
Val tags: Dataset[IdsWithTags] = odsWithArea.map(createTags)
}
//添加列可以来一个 map ,把 map 里所做的事移出来放到方法当中去做,这样整体的代码结构会比较好一些。
接着创建一个Tag”createTags”
这样的方法,接收一个数据;假如说把 createTags 方法放到 odsWithArea.map 里直接传进来,这个时候问题就是 createTags 这个方法当中接收什么内容?
应该接收一个 Row 对象,因为odsWithArea
是从odsWithGeoHash
中读出来,再进行一些转换得到的,而odsWithGeoHash
又是直接从库里面读出来的,库里面读出来的永远都是 dateFrame ,如果是这样的话,不管怎么 join ,最终 odsWithArea
当中放的是 Row 对象,或者它是一个 dateFrame, 这样的话 Def createTags 里面接收 Row 对象。
/**
*(3.3)生成标签数据
*Row ->mainId, ids, tags
//把一个 Row 对象转成另外一个对象,这个对象我们可以设计一下,打标签数据集当中要包含 ID、Tags 等数据,首先第一点数据集生成完了以后必须至少要包含 “主 ID 、所有的 ID,还有 Tags (也就是所有的标签信息)这几项数据。
Mainid 是我们后面为图计算来准备的,ids 是因为整个数据集当中会有很多和 ID 有关的字段。比如说打开浏览器找到 Kudu,Tables 里找一个ODS 层的表
这里我们打开 ODS_20190705 表
我们这个数据的模式中有一些列,这些列当中并非所有都可以作 ID,我们先看一些表中的列,首先 uuid 是可以作 ID 的,sessionid能否作 ID 并不知道,也可能是不能的。
再看“imei”明显就是作 ID 的料;“mac”地址指的就是你的网卡地址,所以也可以作 ID;”idfa”和“openudid”是一个广告标识,也可以作为 ID;所以我们这一个数据集当中,有很多列都可以作 ID,这样的话我们就至少要提供一个主 ID,主 ID 的作用就是标识这一条数据,总之就是最终需要有一个能标识数据的 ID。
*Row -> IdWithTags
*/
def createTags(row:Row): IdsWithTags = {
}
case class IdsWithTags(mainId: String, ids: Map[String, String], tags: Map[String, Int])
// 把对应的类创建出来,把 Row 对象转成 class 对象,这个类我们叫做 IdsWithTags,当中我们要先接收一个 String 类型的 mainId,还需要接收一个 Map 类型的 ids,Map 中又包含了一个key,一个value, Key 设为String,
Key 的意思,比如说一个 ID 是uuid ,那么这个 Key 也就应该是uuid , 而 uuid 对应有一个具体的 ID, 那么值也就是这个具体的 ID, 所以这里值也为 String ,还需要生成 Tags ,Tags 也是一个 Map ,因为 Tag 也分好多类 Tag ,并非只有一类,所以这个 Tag 的名字我们就作为Key 放在 Map 当中,然后这个 Tag 的值也就是标签的值我们应该是一个权重信息,这个权重应该作为一个 Int 放入 Map 当中,这样IdsWithTags 就做好了。
做好了以后我们先在这个类当中在这个方法当中把 Row 对象转成一个 IdsWithTags 对象,接下来生成的这个数据集把它放到”def createTags(row:Row): Unit = {“ 这里,变为“def createTags(row:Row): IdsWithTags = {
”;生成的这个数据集就是 val tags,是一个 Dataset 里放入了[IdsWithTags] ,即“Val tags: Dataset[IdsWithTags] = odsWithArea.map(createTags)”
,注意这里不需要下划线。
2.如何把一个 Row 对象转成一个 IdsWithTags 对象?
分两个步骤:
// (3.4) 生成标签数据
(为每条数据打上标签,这样外部的 DSP 在访问我们某一类数据的时候会直接传给我们一个标签,我们可以通过标签来查到对应的人)
val_tags = Map[String, Int]()
// (3.4.1) 广告标识
tags +=
(“AD”+ row.getAs[Long]( fieldName = “adspacetype”)->1)
// 生成第一个标签——广告标识,从 Row 对象中获取到这个广告的标识,它的字段名叫做 adspacetype,它的类型是一个 Long 型的数据,我们拿到这个数据以后就可以把它拼到 tags 里面;此时要考虑这个 tags 现在可以“+=”一条数据吗?这里是不可以的,因为我们只是一个不可变的 Map ,所以要是用可变的 Map 才能动态的往里添加数据,应该在前面加上一个 mutable ,然后导入 mutable 这样一个包;
导完以后还是有一点问题,需到 import 部分把 mutable 给去掉,导一个下划线,或者导一个 mutable 的包都可以,一般情况下的最佳实践是先导,导完后就可以使用 mutable....来创建一个可变的集合,然后通过这个集合直接创建一个不可变的集合,这样比较清晰一些。
tags“+=”后面添加的是一个数据,这个数据的 key 就是刚才取到
的row.getAs[Long]( fieldName = “adspacetype”)
)这一串,
但是如果直接加到 Map 当中别人也不知道这是哪种标签,所以在标
签的名字上要加一个“AD”就标注这是一个广告的标签 ;因为是一
个 Map,所以往里面添加肯定是一个二元元素,要在后面给一个
“1”,这个“1”就是它的权重。
// (3.4.2) 渠道信息
tags +=
(“CH”+ row.getAs[String]( fieldName = “channelid”)->1)
// 渠道信息可以通过“CH”+ row.getAs
传入fieldName = “channelid”
,类型为 String, 初始权重为“1”来添加。
// (3.4.3) 关键词 keywords -> 帅哥,有钱
row.getAs[String]( fieldName = “keywords”).split(regex = “
,”)
.map(
“KW”+_ -> 1)
.foreach(tags += +_)
// 还是通过 Tags 来添加信息,但是这里不能直接加,首先通过Row.getAs
获取“keywords”
,不同的关键词之间有一个分隔符,指定类型后可以直接 split,split 用逗号regex = “,”来进行,这里类型为 String; 另起一行 map,这个 map 当中拿到的是每一个split(regex = “,”
过的数据当中的一个元素,例第一项在 map 当中拿到的是帅哥,第二项拿到的是一个有钱,所以就直接拿到下划线,让它对应一个“1”返回,这个时候就返回了一堆二元元组出去,就可以把它命名为 keywords, 之后就可以把 keywords 加到 tags 当中为【Val keywords = row.getAs[String]( fieldName = “keywords”).split(regex = “,”)】
,但是这个方法还是不太好的,这样去加的话比较麻烦,可以把 keywords 删掉。
使用 foreach 来编写,编写时拿到 tags 内容,直接加上下划线,它对应的是一个二元的元组,此时把里面的每一项都拼到这个tags、map 当中,
// (3.4.4) 省市标签
tags +=
(“PN”+ row.getAs[String]( fieldName = “region”)->1)
tags +=
(“CN”+ row.getAs[String]( fieldName = “city”)->1)
// 使用 tags += 省标签“PN”加上 row.getAs( fieldName = “region”),
取出来为 String 信息,再一个箭头指向“1”,这个时候就生成了 一个二元元组添加进去。接着添加市标签“CN”,这个市的字段叫做“city”。
// (3.4.5) 性别标签
tags +=
(“GD”+ row.getAs[String]( fieldName = “sex”)->1)
// (3.4.6) 年龄标签
tags +=
(“AG”+ row.getAs[String]( fieldName = “age”)->1)
// (3.4.7) 商圈标签,正常情况下在这里需要生成 GeoHash,然后再查询 Kudu 表,获取数据
//优化写法,直接先进行 join,把商圈信息添加进来,然后直接取
row.getAs[String]( fieldName = “area”).split( regex = “
,”)
tags +=
(“AE”+ row.getAs[String]( fieldName = “area”)->1)
.map
(“A”+ _-> 1)
.foreach(tags += _)
// (3.5) 生成 mainId