00:00
呃,接下来我们最后还有各个类别的top ten,或者说我们top多少都可以,对不对,我们这个自己定义就可以了,那在这个统计里边,我们一开始要做一个什么事情呢?大家会想到我既然要找各个类别的top统计,那是不是我先得知道有哪些类别啊啊,当然了,这里就是要定义出来所有类别,呃,那我们标准的一个做法,其实你是应该从数据里边是不是做一个便利,做一个提取啊,我们这里边就就简单去写了啊,大家看我在本身的文档里边已经把我们看一下,这个已经把所有的类别给大家总结出来了,这个大概应该是20个类别吧,好像是。可能不到20个或者是19个这样的一个类别,大家会看到我是存了一个什么数据类型,对,存成了一个list啊,这个是我们比较简单的一种实现,就先把它放在这里,作为一个常量放在这里,然后大家会想到我们要做的事情是什么呢?是不是应该根据每一个类别?
01:12
要选出含有这个类别,就是,呃,大家想是属于这一类别,有这个类别标签的电影,要这一类全选出来对不对,但是电影的那个标签里边,大家还记得它是怎么做的吗?啊,这这个太难看了啊,我们还是data loader里面看这个样例类,我们这里边是不是一个电影有可能有多个类型啊,然后用竖线分割对不对?哎,那大家就会想到,在这个判断的过程当中,其实我们是不是要比方说我们这个action这个类型,要找它对应的电影,是不是只要电影的这个runros类型这个字段包含action这个词,我们是不是应应该算它就属于这类啊,那同样它可能还属于adventure对不对,还属于这个科幻对吧?所以我们的选择其实是要判断每一个类别,然后再判断每一个电影它的那个类别那一项里边是不是还有这个词,对不对,对应当前类别的这个词,所以这是我们想要去做的一个考察,呃,那在这个过程当中,大家会想到我应该去做一个什么样的操作呢?
02:33
呃,首首先我们是不是前提我们要选这个top,根据什么判断top是不是评分的top啊,我们是不是应该先把电影后面他的评分要先拿到电影的评分在哪里把。我们有有的平分数据,是不是平均评分啊,每个电影的平均评分是不是已经拿到了,我们是不是可以把这个平均评分从前边我们是不是已经存在了这个average movie df里边啊,我们是不是可以把它提取出来,加入到电影表里边啊,是不是这样,电影表那就相当于加了一列,对吧?那这种加一列的方式我们怎么去操作呢?怎么去操作这个加一列,大家想一下。
03:33
最后我们得到的应该是一个新的表,一个movie可能要with score对不对,一带着评分的一个新的表,哎,那大家就想到,那你要得到一个新的表,是不是我把之前的这个表跟这个DF做一个draw是不是就可以了,哎,所以这个其实很简单啊,那大家想一下,我们要做的是一个是一个什么什么状意呢?左左外连接还是左外连接是吗?
04:05
也就是说,假如说这个电影没有评分的话,我们之后还考虑不考虑它主要是这个问题对不对?因为左外连接的话,相当于就是说如果它那个评分没有统计出来的话,没有人看过这个电影的话,就没有评分,对不对?那大家想如果没有人看过这个电影的话,我们会把它加入到最后类别top ten的统计里边吗?其实是不是完全没有啊,所以我们选出来的一定是既有电影内容信息,又有平均评分统计的,对不对?那我们这个照应应该做什么什一个什么照应,对这个是不是就应该是一个婴儿照应啊?好,那这里边我们是不是movie df要跟average要做一个inner drawing啊,这里边drawing average movie df,那大家知道,如果我们不给参数的话,后边可以直接。
05:05
给定要draw的这个字段,那么它是不是默认就是一个inner drawing啊,啊,大家如果不太确定的话,还是点回去看一看,它这个说的到底是什么,是不是婴儿join应啊,对吧?所以这个没问题啊,好,那么我们把这个照应起来之后,就已经拿到了每个电影,而且带着这个平均评分的数据,那之后我们怎么样去把这个类别和每一个电影做匹配的考察呢?那接下来我们这个操作有点像是对于每一个类是不是要跟每一个电影都去考察一下对不对?这是不是有点像两个集合要一一元素一一对应,这是不是有点像笛卡尔机的那种方式啊,全外连接对不对啊,大家有点像这个方式,所以我们一个简单的想法式,先做一个笛卡耳机,然后进行过滤,对不对?把里边不符合我们要求的过滤掉,最后选出来的是不是就是这个类别,而且符合这个类别的电影啊,哎,这就是我们想要的,好,接下来我们啊,那如果要做笛卡耳机的话,我们可能需要笛卡机,我们需要用RDD来做操作,对不对?那这里我们本身的这个类别信息是一个例子的,那显然是不行的,所以呃,为。
06:31
做笛卡尔机把runs转成RDD,呃,这个其实就是我们可以定义一个runners r DD,它是不是可,呃,它是不是可以用这个Spark。这个。Sparks sc里边的这个叫做make r DD,方法对不对啊,可以把它转成一个RDD,那我们把这个runros传进去,好,有了这个runs r DD,然后我们是不是就可以让它跟前面得到的movie with sc,然后做一个笛卡尔机啊,然后接下来就可以做过滤了,对吧?好,那我们这里边计算类别top ten首先对呃,每对类别和电影做笛卡耳机。
07:41
就是要一一配对对不对啊,做一个类似于全外连接的一个东西,好,那么我们这个把它定义成最后想要得到的,要存储的,我们是叫做runor top movies,直接把它定义出来,然后我们得到的应该也是一个DF,对吧?最后存到猫go里面去,这是我们想要得到的结果,它怎么样去做操作呢?前面是不是rovers r DD d卡机是什么?这个大家之前用过吗?啊,看S对吧?然后里边是不是要传入另外一个RDD啊,这个RDD我们是不是可以直接从movie with score里边做一个点RDD操作,把它转过去啊,好,这样的话得到的就是一一对应的那个关系,接下来是不是可以做一个filter,做一个筛选,我们希望筛选什么样的东西出来呢?
08:39
大家会想到我是不是想要筛选出这个类别真正对应到这个电影里边,这个电影的真正属于这一类对不对,想要筛选出他们类别一一对应的那种关系对不对?所以我们这里边怎么写这个条件呢?
09:01
我们需要找出是不是本身movie with score,这个movie里边有一个字段叫做什么,是不是叫做movie的字段,有一个字段是不是就叫做runs啊,它的类别是不是就叫这个这个字段,那么它的字段值如果包含。当前的这个类别的话,就是我们这个ROSRTD里面这个类别对不对?那个字段它是一串字符串,用竖线分割的一组类别,如果包含当前的这个类别的话,是不是表示这就符合我们的要求对不对,它就符合属于这一类对吧?所以我们要找出movie的字段runs值包含当前类别的,呃,那些就就直接这么写就可以了,大家知道什么意思就好,对吧?那当然filter的过程当中,我们最好还是来做一个模式匹配,那么这个case大家会想到前面是不是是某一个种类对不对?大家看我这里边没有加S对吧?Run那是每某一个种类,然后后边是不是相当于是一行数据啊。
10:21
大家会想到这是一行电影的完整信息,对不对,这是这是一行数据,然后我们把它转成一个做一个什么样的操作呢?做一个什么样的操作,因为大家想到我们接下来返回的一个东西,应该是一个条件判断,对吧,是不是一个条件判断啊,我们要做filter里边是不是应该给条件判断,所以我们应该是对,是不是应该是有一个包含啊,Contain对不对,Contains,那么谁包含谁呢?对,是不是这个肉里边,这是我们电影的完整信息,对吧?我们是不是要取出对应的那个字段,哪个字段呢?
11:04
是不是大家会想到我要取哪个字段,是不是就是这个runrous这个字段啊,我们把它那个get as什么,它应该是一个,是不是一个字符串啊,大家想一想是不是,是不是选取出类别这个信息,然后把它作为一个字符串取出来对吧?然后大家会想到是不是它就可以去找它contains了啊,当然为了防止大家看到这里边有大小写的关系,为了防止出现这个大小写的意外,我们是不是可以把它先做一个to lower case的操作啊,啊,先转成统一的这个小写,接下来是不是可以contains一个值,那大家看现在就不报错了对不对?因为我们这里边应该是一个条件判断,对吧?这里边啊,条件过滤,那contains什么呢?我们想要让后面电影信息那个类别那一列里边包含当前的这个类,对不对,那应该contains什么。
12:17
大家想一下,是不是就是contain,我们当前的这个rora啊,就前面拿到的这个东西啊,是不是这样啊,当然为了方便我们的这个大小写这个,呃,排除大小写的关系啊,就是忽忽略大小写不敏感的话,是不是也要把它做这个图lower case啊,所以大家看尽管写出来一长串,它其实核心就是我们说的是要找到movie字段,它的这个runrs类别里边。包含当前类别run的那些,对不对,对吧,大家想一下是不是这样。呃,有有有一点难理解是不是,那那我们还是给大家想一下,在这个movie的这个字段里边啊,比方说这个肉我们写成这个movie肉吧,Movie肉对不对?然后这里边大家会想到movie这里边它的每一行应该是什么数据呢?是不是前面我们定义好的这些数据啊,然后我们想要的类别信息在哪里?
13:27
是不是在这里啊,Runs对不对,所以我们是不是要把这个runs信息拿出来,他拿出来是个什么东西呢。Runros这个值拿出来之后,是不是应该对应的是这样的一组值啊,对不对?所以我们其实是要从这个值里边包含某一类,对不对?那大家想,假如说我们考察的这一类当前就叫action的话,那是不是它只要包含action这个字符串,我们就认为它俩匹配上了呀,我们要的是不是这个效果啊?所以我们其实就是要找到这个字段值这么一串,看它是否包含我们当前的这个类别。
14:17
大家这样看可能能看的稍微清楚一点,对吧?好,我们继续往后面实现,呃,我们把这一部分如果做了过滤之后,接下来这拿到的其实就是每一个类别对应的电影是不是就都拿到了,但是他们是一一匹配的,对吧?所以我们是不是还要根据类别去做一个,大家会想到是不是应该根据类别去做一个聚合啊,那在做聚合之前,我们先做一个预处理,我们先做一个map,把它转换成我们想要的形式,呃,那当然了,这里边大家可以想到我还可以是这样的一个模式匹配,把它做一个转换对不对,转换成什么样子呢?我最后想要的可能就是前边这是我的K,是一个runner类别,对不对?后边我想要的是不是应该是把想要的数据拿出来。
15:17
来就可以了,不需要完整的那个电影信息全跟在后边对吧?我们最后想要的是什么呢?大家不要忘记,我们最后想要存到mongo里面的数据结构是我们定义的这个case class的这种形式,对不对?所以前边是runs,后边是不是应该是这样的一个列表啊,那这样的一个列表里边的元素是不是应该是这个recommendation这对象啊,那应该是一个mid加一个score对吧?啊,大家不要忘记我们的初心,就一开始我们就构想出来想要的是这样的一个数据结构,所以我们把它包包装好,前边一个mid,后边一个score,对不对?那这个mid是什么呢?那就得从movie roll里边去选了,对吧?Movie roll里边我们是不是可以同样也可以用get as对吧?拿到了mid是不是应该是一个int类型啊,诶把它拿过拿拿到接下来大家会想到。
16:17
Movie roll还要拿到他的score score是什么呢?对,大家会想到应该是一个double类型,那么这个字段就叫做score,这样把它拿出来,大家会看到我们经过这个包装之后,这是不是就是我们最后想要的那种格式啊?然后接下来做什么操作,是不是要对这个K做一个聚合group by啊,因为我们现在拿到的还是每一个类别后面跟着一组那。同样类别的是不是它们都是不同的元素啊,对吧,都是一个类别后面跟着一一个这样的一个元素,一个类别跟着一个元组,所以接下来我们会对它做一个group by,是不是直直接grew by k就可以了,我们当前的K应该就是前面这个run对吧?类别根据这个做一个聚合,然后做一个分组啊,大家会想到接下来我们是不是就是要把它转成我们想要的数据结构啊,Recommendation对不对?呃,所以最后再做一个map,那这里边map之后。
17:29
我们还是用模式匹配这种形式写啊,这里面我们拿到的应该是什么呢?是不是一个类别run对应后边应该是一组这样的一个信息啊,对吧,所以我们把这个叫做it吧。我们最后想要做什么操作,是不是要把它转换成我们定义好的runs recommendation这样的一个数据结构,这是我们定义好的样例类啊,好,这是我们最后的目标,然后前面第一个参数是不是就是我们这里定义好的run单一的类别对不对?这里定义好的啊,然后后边的数据是什么呢?是不是应该是一组recommendation啊,我们要把这个items里面的数据转换成一组recommendation,而且我们是不是还想根据大小做排序啊?
18:27
哎,那大大家会想到这个items,它本身是个什么东西呢?大家会看到它其实是我们前面做了这个group by之后拿到的东西,对不对,我们拿到了这个东西是不是应该是一个RDD啊,所以它合起来之后,这个东西我们大家想我们想要去做排序的话,是不是可以直接想应该有这个salt方法对不对,但是看好像他没有这个sot方法。对,那大家想到是不是list就直接有这个sort方法啊,那我们再把它做一个转换是不是就可以了?对,所以items可以对它做一个list to list的操操作,然后再调用with方法。
19:10
那south with什么呢?大家看到里边我们south是不是可以有一个里边可以有一个表达式啊,有一个布尔类型的表达式对不对?表呃,表示我们做排序的一个原则,那我们这里是不是要按降序排序,按谁的降序排序呢?哎,大家看这里边我们的元素是不是应该是前面int,后面double这样的一个类型啊,一个元组对不对?那我们是不是要把每一个元组里边的。大家想到是不是第二个元素去做一个排序啊,大家也见过这样的写法,用过这样的写法对不对,那我是不是可以对第二个元素大于第二个元素,这是不是代表按照第二个元素降序排序,哎,就是这样的一个做法啊,然后我们还要选取top ten呢。
20:02
那怎么办?对点take对吧,Take,然后直接选选取前十个,这是不是就是top ten啊啊,当然了,最后我们可能还要把它再做一个map操作,是不是要每一个元素都转换成我们想要的recommendation对象啊,所以这里边的这个元素一个item,我们把它。转换成想要的一个,呃,这里啊,Recommendation recommendation,呃,里边当然就是我们要它的item,这本身item里面有两个元素,那我们recommendation里边也是两个元素,对不对?那是不是就把item的第一个元素付给我们的?Mid对不对,然后第二个元素付给我们的第二个元素是不是就是它的那个score啊,所以这是不是就是最后推荐出来的这个内容。
21:03
啊,但如果看着这个不太顺眼的话,那我们还是放在一行吧,尽管这个有点有点长了,对吧,我们把这个放在一行,那大家会看到我这里边做了正常的一串操作,其实就是。把我们整个前面拿到的所有数据是不是转换成了想要的这个样例类,这个数据类型啊,然后是不是就可以把它存到呃,对应的这个mango里面去了啊,那当然这个这里边我们拿到的应该还是一个,我们再把它做这个图DF对不对,拿到前面还是RDD啊,所以后面我们做一个图DF,最后是不是调用方法store in df in bgo DB,我们把这个top movies df存入到。对应的表里边,这样是不是就结束了啊,这就是我们整个统计推荐四部分内容就这样完成,可能最后这一部分是呃,处理最复杂的一类,对吧?大家也可以自己去写这个CQ,那CQ实现其实大家能想到,因为涉及到我们要一一匹配,然后要做过滤,筛选出他们匹配字符,字符匹配的那个过程,那有可能我们自己是不是也要去定义一些udf啊,对吧,还可能还需要用到这个爆炸函数之类的东西,所以其实实现起来也比较复杂,所以大家可以看看自己习惯用哪种方法,这其实就是我们不同的方法都给大家复习一下,大家熟悉一下我们这些内容就就好了。
22:36
好,那这部分已经做完,我们当然还是要跑一下看看它的效果怎么样,呃呃,当然刚才我们改了一下,大家注意把这个SC改过来啊,刚才的一个bug我们现在看一眼,应该在mongo里边,大家预计应该出现一个什么样的对,应该出现四个新的表,对不对?哎,所以大家看到除了我们一开始的movie RA tag这三个数据表之外,是不是还有了average movies平均评分啊,Runs top movies top ten类别top ten,对吧?然后还有这个more movies,这是对历史评分最多历史热门对不对?还有一个recently,这是近期热门啊,所以大家会看一下大家对哪个感兴趣,我们就看一眼这个average吧。
23:25
Find pretty大家看一下里面到底是什么东西啊啊,或者大家如果要是觉得就是那个数据太多的话,我们是不是翻one看一条也就知道大概是什么样子了啊,诶大家看这里边一条数据就这样,为什么呢?因为是不是里边只有一个平均评分数据啊,大家看电影1088这个电影它的平均评分3.35就看起来不咋地对吧?啊,就是这样的一个一个评评分,那当然如果大家想看一下的话,我们看看所有的电影都有对应的这样的一个。
24:01
呃,啊,当然我们在做平均评分的时候,好像没有加排序是不是啊,大家看到我们这里边这个排序是乱的对吧?有这个二点几的,有三点几的,大家如果愿意的话,这个很简单,一个order back搞定对不对?呃,所以这个我们就不详细讲了啊呃,然后我们再看一下大家还对哪个感兴趣,我们可能对那个top ten感兴趣对不对?那个前面费了半天劲把它写出来啊,Find pretty。而大家看这个推出来的是一个什么东西啊。这就是我们想要的那个结果对不对,就是诶最外面有一个K叫做runners,这是它的类别对不对,这S,这是一个浪漫类别的电影,电影,然后后边一个值是它的,相当于就是推荐列表对不对?那它的推荐列表里边有十个元素top ten,它按什么排列呢?是不是按照平分,平均评分的大小来排排列啊,当然这里边大家看到这个全是五分对吧?这个平均评分全是五分,然后里边的数据结构就是一个mid对应一个评分,一个mid对应一个评分。
25:09
那上面大家看到这就不是全是五分了,有4.67的,有4.5的对不对,大家看这个推出来的这些大部分评分还是很高啊,平均评分全是五,这个这个确实很厉害。就top ten推出来的好像都是啊,大家看这里边有这个4.5的,4.4的对吧,就是也是这看哪个类别,比方说像这个犯罪类别可能好电影不多啊,那就有可能会推出来的,就分会低一些,对不对,有一些类别他可能像这个啊呃,Documentary这个是什么类别,这个一下不知道啊。Horror,这个是恐怖片对不对?恐怖片看起来好片比较多啊,就高分很多,所以这就是我们推出来统计推荐的一个结果。那当然了,就是大家会想到实际在去做这个,呃推荐的时候,我们查这个对应的表,那其实在业务系统里边,即即使我们这个平均评分这里没有做group,呃,那个order by业务系统是不是也可以在查mango的时候做一个排序啊,呃,也是可以的,对吧?所以说其实我们只要把数据写进去,这个从从这个性能考虑的话,我们这里先把它做一个orderb,当然是最好的一个选择,大家自己把它做一个丰富就可以了。
我来说两句