00:00
好,接下来呢,进入我们dew第一个需求对吧,这个呢,因为咱们用的是link circle啊,我们稍微写一下,这个呢,我们用的是link circle,原因呢也跟大家说了,对吧,我们还有一些东西要练习一下啊好呃,那第一个需求是这样的流量语。诶,那这就是行为数据日志数据里边的内容,对吧,我们呢。来源,关键词力度。啊,然后呢,页面浏览各窗口的汇总表。啊,各窗口的汇总表OK吧,好,那这个需求讲的什么意思呢?实际上因为要看这个名字啊,就有时候不太能了解到它什么意思,对吧?啊我就简单介绍一下,就是说你看在我们无论是这个。京东。淘宝它都有这个自己的搜索框。对不对,没毛病吧,好,那我们呢,用这个搜索框。
01:02
去查询我们想要的信息,这就是我们搜索的关键词。对吧,那我们要去统计一下,那用户在做这种关键词搜索的时候。啊,他在做这个关键词搜索的时候,他高频的词到底是什么呢。我们想了解一下对吧,用户呢,他经常搜的词。是哪些呢?咱们主要想了解一下这个事情。啊,咱们主要想了解一下这个事情。OK吧,所以呢很简单,就是说呢,把用户搜索的关键词来。咱们打开一个这个行为数据的示例啊呃,这里面呢,我去找一个啊给大家。
02:00
Search。嗯,当前是搜索页,诶比如说这个。对吧,那这个人呢,搜索了苹果手机,有可能呢,他搜索的是牛总爱唱歌。对吧,啊有可能啊,说牛总爱唱歌啊,那搜索的关键词,那我们呢,要对搜索的关键词进行一个。分析对吧,做一个词频统计。啊,就做这事,所以呢叫这个什么来源关键词力度对吧,最重要的关键词做一个词频统计,然后呢,说求的是页面浏览,那就是。总次数对吧?搜索的总次数其实就是一个简单的,我好,那我问大家啊,就是如果说我搜索了一个关键词,这个关键词呢很长,哎,那我问大家啊,我是把这个关键词整体做K去统计,我count还是应该把这个搜索的关键词对吧?就像牛总爱唱歌,把它做一个加工以后。
03:10
再进行。食品统计呢?是直接当做一个整体。还是应该把它加工一下,诶把它切一切啊,类似于这样子的。做一个加工以后我们再来。做统计啊,应该是什么样子。哎,要加工要做。分词。对吧,没毛病啊对,很明显要做分词啊,那分词大家想到了什么呢。提到分词,大家应该。
04:00
啊,直接就想到了ES没毛病啊,确实就是分词呢,我们只在ES去学过啊,嗯,那我要问大家,哎,那是不是这个需求咱们用ES存能好一点呢,我不要用这个。可以号去存了,我用ES去存是不是好一点呢,大家觉得。那你不要分词嘛。我是不是应该用ES存呢,而不用克列号去存呢?啊,陈总觉得是其他同学呢。
05:03
其他同学是怎么认为的?啊,因为提到分词呢,我们只学过这个ES。对吧。那我们自然而然然想到,我们是不是应该用这个ES作为这个数据的存储,而不要用这个。Click house。大家是怎么认为的?嗯。没有想法。我告诉你啊,用ES不行啊,那你想一下ES分词干嘛呀,它分词以后见索引。
06:03
对吧,诶是他把这个词分了,但是我们现在分词要干嘛呀。我们现在分词要。做词品统计,就是这个词我得拿到,然后呢,我还得统计它有多少个。对吧,你拿ES来存储有什么用啊,他给你分词了,是他给你分词,然后呢,你能拿到这个分词吗。拿不到。对吧?啊,所以呢,我们不能用E做存储啊,也就是说这个分词呢,咱们得自己写啊,咱们得自己写。把这个词呢,假如苹果手机对吧,就看这个关键词啊,我把它拆分成苹果和手机两个词啊,好,那在搜个里边,我们拆成两个词以后再做这个词幂统计,这个东西应该用什么函数啊。咱们应该用什么函数啊。
07:02
哎,刘总说了,炸裂没毛病啊,就要用炸裂啊,用UDTF,所以呢,这个需求我们里边呢要用到。我们要自己写一个。战列函数。而且呢,还得是有分词功能。对吧?啊,那我们知道ES呢,它能够做分词,它是不是依赖于一个东西叫分词器做的分词啊,那我们。自己调用分值器的API来自己写这个分词的一个逻辑不就行了吗?对吧,啊,所以呢,这里面我们要自定义函数,自己去写这个分词啊好,那我们的需求就明确了,那很简单了,对吧,第一消费这个。配置log主题的数据对吧,接下来呢,做过滤,因为我们要的是搜索的。数据对吧,你有的内容呢,不是搜索的,你比如说这个配,你虽然是一个配置,但是呢,你访问的是一个主页,对吧,你就正常点到主页,这条数据呢,我得过滤掉,我得有这个什么搜索关键词才可以,我才需要。
08:10
对吧,我得有它。啊才可以对吧,Item type呢,Keyword对吧,它是一个关键词,那第二个呢是过滤,过滤好以后呢,我们要自定义函数做分词,分好词以后。求我。啊,求我看最终呢,把我们数据写到这个house里边,对吧?啊当然。在求我的时候呢,咱们是分组开窗去求的,对吧,啊组呢,就是关键词嘛,对吧,那开窗。正常开窗,这是我们也说的。在弗林搜里边,我们目前。当前这个项目里边还没有用过开窗呢。对吧,好,那你开窗我们肯定用用这个实践时间会更好一点,所以呢,又引出来了,在这个数据当中,我们读取数据的时候,我们得根据。
09:01
里边的TS。来提取时间桌生成wordma,在S里边,我们要去生成这个wordma对吧,所以呢,我们几个关键点内容都出来了。开窗,十点时间开窗,山成奥特曼。自定义udtf函数对吧?啊,这三个关键点我们这就说了啊,这个需求当中呢,都可以包含了,OK吧?好,这是我们需求分析啊,这是我们刚才所提到的这样的一个事情啊。好,这里面呢,要有这个分词对吧?啊,要有这个分词啊,然后呢,这是过滤条件,我们要过滤啊,整个内容最后呢,写到这个clearhouse里边对吧?好,那我们整个来看一下我们整个这个内容啊。嗯,这边呢,我还是打开一个。模板。来把这个流程我们去了解一下。其实刚才呢,我已经都说出来了,对吧?第一步诶,我们把这个工具类先准备好啊,然后呢,写这个自定义的UDTF函数做好准备,对吧?啊那这个呢,我们要用跟ES一样的,用IK分词器啊,要用IK分割器定义分词的方法,对吧?调用IK分割器啊,去做一个分词啊,就是进来一个关键词,但是拆出去一个集合。
10:21
好吧,好,那通过这个工具类呢,去写一个自定义函数。啊,当然这是一个UD。TF啊,它是一个UDTF。对吧,Table function啊是一个table function,然后呢,实现这个分词的逻辑啊好,那这个搞定以后呢,我们就注册函数,未来要用嘛,对吧,要注册函数啊,当然注册呢,得我们写正常的数据流的代码的时候才能去写这个内容,对吧,那主流怎么来呢。消费。页面主题数据对吧,就是配置到。啊,配置logo。好,同时呢,我们要提取时间桌,生成wordma,这并设置水位线,这个呢,在我们建表的时候就要搞定这个事儿,最早建表的时候就要搞定这个事儿啊好,那么接下来呢。
11:11
过滤我们的要的数据吗?过滤出我们要的这个搜索数据。好,那接下来。分词对吧,这是我们的判断字段啊,最后呢,我们要做这个。分词对吧,接下来分词,分词呢,用过滤后的数据结合我们注册好的函数进行一个分词对吧,它俩一结合,哎,做一个分词,分好词以后呢,就接着写到了,正常的分组开窗做聚合,最后呢,把这个数据要写到。克house对吧?啊,写到这个科house里面就行了啊。转化为硫进行写出啊呃,至于为什么转化为硫呢?第一,你flink circle里边它没有click house的一个连接器。第二我们呢,未来除了DS第一个需求我们用的link circle,其他的需求那都是用的什么。
12:05
Data stream,所以呢,前面我们可以在这儿写一次,对吧,写一个封装好一个工具类,那未来呢,我们就都不用写了啊,它为了后面可以复用嘛,对吧,我们就都用一个啊,虽然你第一个用的flink circle,但是我也没必要额外的去写了,我就直接封装一个工具类对吧?为了后面呢,我们可以统一的去做梳理啊,那还是一样的,我们就写好一个工具类嘛,那不管怎么样,他还得是这个什么。调用GDBC.s因为牛嘛,你也通过JDBC可以访问对吧,所以呢,还是JDBCS,因为你这个地方就单表单表了,对吧,只有前面我们DM没有用到这个。JDBC,那是因为。DM呢,它一个流里边有太多种表的数据了,没办法用。G bc single,而这个地方DWS,那肯定就是独立的一张表一张表,那我们就。用一个GDP写出去就好了,对吧?好,这是我们整个的数据流啊,接下来呢,我们就要围绕这个内容把这个去写一写啊,但是并不简单啊,虽然我们又用的是弗Li s,但是我告诉大家并不简单好吧。
13:14
呃,这里边呢,先写了一个可house建表语句,但是呢,我们先不要着急,最后呢,我们再来聊这个事儿到底应该怎么做,对吧?现在呢,我们把这个建表语句粘进去不太好,因为我们关于克里奥要用什么引擎。要怎么去存这个数据对吧?啊,我们到时候后面还得都得讨论一下这个事儿啊,都得讨论一下这个事儿对吧,那我们前面像过滤呀,还有切磁呀,这个事儿我们都可以直接做了啊,那最后呢,磁频统计就是说你要分组开窗聚合这一步呢。我们就可以讨论最终我们要存什么数据,因为你会影响到最终结果,你需要取哪些字段,那你表需要哪些字段,我们就取哪些字段,没毛病吧?
14:00
对吧,这个意思啊,所以呢,我们先不着急在科学号里面去建表,先把呢核心的一些东西把它写了啊,比如说你们要过滤,要贴磁对吧?啊提取时间戳生成沃慢,然后最后呢,要准备做分组开张聚合之前,我们再想一想,这克雷奥里边应该存什么数据,怎么存。对吧?啊,因为这样的话,我们分组开张聚合的时候,我就知道我需要保留哪些字段啊,有不需要的字段我们就干掉,对吧?好啊,那第一步呢,咱们写代码的时候,先写这个UDTF函数。对吧,先把它搞定啊,那首先呢,我们得有一个工具类啊,先把这个IK分支器的依赖搞进来。我们要利用这个IK分词器来做这个事情。依赖啊,那这个跟前面依赖没什么关系,我就直接往后添加。往这放可以吧,哎,这是一个IK分子器的依赖,接下来呢,我们就要写一个工具类啊,以达到我们切磁的一个功能啊,来到我们的这儿,我们写一个。
15:02
叫keyword。关键词的一个工具类,OK吧,好,那这里边呢,Public。返回值是什么类型啊,那我们想啊,它的输入参数肯定是spring字符串,我们要把这个字符串做一个什么切分,切分成好多个小字符串。那我们统一的返回,那得用一个。List对吧,啊,得用一个list对,用一个集合来做这个数据的存储。啊,那这个呢,我们就叫Li。叫keyword吧,好,那参数呢,我们刚才说的那就是keyword。关键词对吧,好,那首先呢,创建集合这里边呢。创建集合,用于存放。切分后的。
16:02
数据。对吧,哎,好,那另一个list。得到一个类似啊,那最后呢,我们肯定要把这个词放进去,以后干什么事,把这个集合做一个返回,对吧,最终。最终返回集合啊,返回结合。List好,这两步倒没有什么问题,对吧,跟我们这个IK分子器呢,也没有什么关系,那不管怎么样,中间呢,我们要利用IK分子器去做切词,然后呢,把一个一个切出来,词呢放到这个集合里边。对吧,咱们要做的事情是这样子的,好,那接下来这块代码大家都不太熟悉了啊,那我们就直接写一下啊,但是不难啊,你看一下你看一下,因为之前大家在呃,虽然了解过这个分词对吧,切词那ES它内部。包装好的,那IK呢,我们也知道这个名词,但是呢,它这个插件你直接给他扔到了ES的一个plug目录底下。
17:08
对吧,你没有接触过任何的代码啊,所以呢,对于大家来说呢,不熟,所以你再看一下啊,那就创建分子对象。我们要去创建这个IK的分词对象,对吧,那怎么做呢,有一个IK。State。好得到这个对象,那他报错,呃,它的括号报错,那就没给参数,它没有这个空参的。构造方法对吧?好,那我们看一下。它呢要两个参数,第一个都一样。两个重载的方法,第一个参数一样,要一个什么叫reader,哎,Reader是音input的,就是说呢,你得给我一个。输入我到底要切什么,你得告诉我吧,第二个参数很明显是一个配置信息对吧?呃,上面呢是bar类型,就是单个配置信息,你给一个,第二个呢是configuration,就是说你要给一个配置信息对象。
18:07
然后这个配置信息对象里边呢,有很多的配置信息。对吧,好,那我们可以用上面这个。第二个参数大家可还记得?第二参数类型叫smart。他跟我们当时在ES里边学习的这个IP分析什么东西有关系啊。啊。跟我们学习IP分子器的。时候跟什么都有关系啊,你你看到这个use smart,你能不能想起来一点东西。啊,你能不能想起来一点东西。诶,方总说的最细分词分词原则,对,他认为有两种规则呀。
19:03
一种呢叫I k smart,大家还记得吗?还有一种叫I k ma world对吧?第二个参数啊,注意它呢,有一个IK什么smart。还有一个呢,叫AK。叫max。Word对吧,是不是有两种规则呀,对吧?好,第二个参数其实就做这个事的啊,那你要to,那人家用的就是X smart,你要写的是false,对吧,他用的就是。Max word这种形式对吧,但是这个呢都还好,我随便给对吧,两个呢,我到时候测一下关键第一个啊,那咱们呢,知道他要一个input,就是你要分词的对象,那我们很明显这个分词对象应该是谁啊,是这个keyword吧,对吧,那但是他的对象呢,要一个read类型,那我们现在想办法把这个什么。变成一个。Reader。对吧,变成一个reader四面类型啊,那这边呢,我们就只能用一个用一个。
20:05
Three。Reader,哎,然后呢,把这个keyword放进去啊,还让V得到一个什么呢,Reader接下来把它。扔进去。把他扔进去。对吧,你们要一个reader吗?那我们有一个reader,然后呢,把这个关键词传进去啊,那之后呢,我们就可以拿着这个。它里边就包含一个一个词了,那我们就拿它取出一个一个词进行遍历,对吧?遍历好之后呢,我们里面放啊,那我们就拿这个对象来取出切好的词。叫IK点,哎,那就next。有next对吧,那我肯定用next啊好,那很明显这边呢,我们是不是得写一个循环,大家想。如果说我只是这样调用啊,一个next对吧?啊一个next啊接下来呢,它前面的词我告诉你啊,这个next点啊,前面的词是什么呢?这个。
21:11
这就要一个一个单词,然后呢,你把这个单词对吧,List点把这个word看进去,这样对吗。这样对吧,这样你只拿到了第一个词对吧,很明显我们得用一个什么循环对吧?好,那怎么写呢?这边我们加一个循环。取出切分好的词,那就这样啊,While。Next。不等于。那。我们做这个事儿,但是这个不行,这个肯定不行,对吧,因为你控制循环的这个变量在里边。根本就没有变过,那如果说它这个词只要不等于呢,它不永远都变了,对吧,所以呢,我们还要做什么事,这个。
22:06
对吧,那你看你只要不等于钠,那我呢,把这个词取出来,取出来之后呢,再指向下一个,直到最后一个,最后一个呢,你再取出来next就是nu值了,对吧,Nu值那就停了就出去,哎,最终呢,把这个集合返回,因为我所有切分出来词都在这儿了。对吧,好,那这里面呢,有异常。I异常对吧,I异常好,那这个异常呢,我们之前提到过,像这种工具类里面异常呢,如果说你未来工具类呢,有多个地方要用,那你就可以怎么做。直接把这个异常呢,给它抛出去,谁调用这个工具类的时候呢,谁去处理这个异常。对吧,啊,谁去处理这个异常就好了,好那么到这个为止呢,咱们那个IK利用IK分器切词就写好了。对吧,这个代码呢,其实并不难啊,只不过说大家呢没接触过啊,所以呢是稍微的用点心看一下啊,这个呢,模仿的去写一写就好了,然后接下来我们做一个测试哈。
23:08
嗯。一条跑一下测试嘛,对吧,嗯,然后呢。点so对吧,打印啊好,那这边呢,比如说我们写这个像硅谷。大数据。像。哎,那中间呢,还加了穿插了有这个中文跟英文对吧?哎,那我们看一下这个在smart模式下,它切出来的词长什么样子啊,来冰心。好,那X smart呢,它一个点就在于它尽量这个词只要能够跟前后能组成词就组成一个对吧,看啊它所有的字呢,只用一次。
24:04
像硅谷大数,诶数据,本来数据是一个词对吧,它没有切分啊,它只是说把大数放在一块了,只是link英文单独实现的实实数对吧?仓啊,那每个字呢,它只用一次啊好,那如果这边呢,我改成for叫用的for的话,就相当于是ma word格式对吧?看啊我把这个截个图啊。这是刚才smart的模式啊,我们再来看max模式。这里边儿有的字呢,就可能会。多次使用你看啊呃,大数数据项有数据有项目,那这很明显呢,这个数用了多次了,对吧,你看12334,然后这个项呢,在大数据项里边有,在这个项目里边也有,然后实时实数。对吧,哎,这些东西呢,都有啊,那我们肯定用这个for,它好像更。贴近于我们生长环境当中对这个分词的一个感觉,对吧?啊,只要你是个词呢,我就给你拆开啊,我就给你拆开做这样的处理,OK吧,好,那这块呢,我们的工具类就。
25:08
搞定了啊,这这一块呢,确实是一点陌生的代码,但是还好这个代码量呢大啊。呃,现在呢,我们这个IK分词的工具类已经有了,那我们要接下来要写的就是这个函数自定义UDTF对吧?好,那这个呢,嗯,大家肯定都忘忘忘完了,因为毕竟。弗林斯克都已经学过去那么久了,而且其实当时学的时候呢,也没讲太长时间,对吧,所以很简单,咱们呢,来打开这个。Li官网对吧,啊,那我们来看一下,模仿一下人家怎么写,那我们就怎么来写的对吧。还是打开我们的一个文档啊,诶现在呢,还没有完全打开,我们现在还点不了一点的话,它就。不让点对吧。
26:01
你们稍微等一下啊。嗯,开着直播这个东西,就每次就会网速就会受到影响,因为直播它比较吃网速哈。你看这边还是还在转啊。这个图还没有加载完成呢啊,我们再等一会儿。还是不行。开着直,每次开着直播打开这些东西就比较慢,我自己打开的时候就会比较快,快很多。还不行,好,可以了。但是第二个玩意又比较慢,那我们看13啊。就不让他加载这个15了,没有意义对吧,直接就切到这个13啊。
27:00
找我们这个table API and circle对吧?啊,那么这里面呢,有一个叫functions啊,Functions这是系统函数,然后呢,Udf用户自定义函数点开对吧,点完之后呢,我们要去看谁啊,看这个table方向吧,看这个UDTF啊直接看它就行了,诶点到这。他跳转不下去呢。稍微等一下。还是慢对吧,这玩意儿。我要拖吧。这是iggate啊I get上面这块应该是我们的a table方向对吧,在这啊,我们今天往上拉了就就。点一下它也到这儿了啊好,那。这是我们的表函数,我们因为因为我们写学过了啊,所以说上面这些东西呢,我们就不看了,我们直接下面看这个例子,因为只是说大家忘了他怎么写嘛,对吧,以我们就直接看这个例子啊,首先呢,你要写一个类,第一个类,然后继承这个table function。
28:06
对吧,然后还要定义这个特殊方式呢,是一个泛型类,你要定一个类型。那这个类型呢,就是你输输出数据的类型,注意它输出数据类型啊,那我们用肉肉呢,可以表示任何的数据类型,对吧,几个列都可以啊好,那这上面呢,有一个注解啊,这个注解呢,定义了output,它输出数据的什么呢?这个是。列列名,默认的列名,而且呢,它定义了有两个列,就是炸裂函数呢,我们知道它是由把这个一行数据对吧,变成多行啊扎列函数是不是一行变多行了。对吧,比如说我现在呢,是这个苹果手机。对吧,我我简写啊,那现在呢,本来它的一行,我现在要变成什么,变成苹果加手机。是不是应该变成两行对吧?好,那么呃,我们正常的下列函数呢,它都是一行变多行,这个没有问题,但是列没有规定啊,列没有规定,你可以原来是一个列,现在还是一个列,你也可以原来是一个列,现在呢是两个列。
29:14
懂吧,这个也可以啊,这个也可以OK吧,好,那他呢,这个例子呢,给他两个列,但我们就是一个列,对吧,我们之前是一个很长的一个字符串,现在呢,把它变成很多短的字符串,但是呢。列的个数还是一个啊,到时候呢,我们就写一个就行了,后面那个干干掉啊,然后里面呢,要写一个这样方法。对吧,参数呢,对,然后呢去切分,切分之后呢,输出connect对吧,用connect输出,诶那我进来一条数据,然后呢,我用循环做输出就是。这不就达到了一进多出吗?对吧,我输入一条,但是输出多条,因为我是循环输出的。
30:00
对吧,就这样的一个效果啊好,那我们就直接我也叫这个玩意得了,对吧?啊叫私立的方式刚好呢,咱们也是做切分啊呃,这个呢,我们就放到方式里边啊。这叫的方式,然后接下来呢,把这个拿过来改吧改吧啊呃,我们业务逻辑确实也很简单,直接把这个拿过来改一改啊。好,呃,对应的依赖呢,我们先倒一下啊,嗯,这个没问题。Table function,诶把这代导一下,呃,这个呢,你就不要加这个对吧?好,那里边有东西要改,你肯定不能那样写啊,第一改这我们呢只有一个列,所以第二个列呢给它干掉。我们只有一个类,叫word。OK吧,啊好,那接下来呢,这个方法,然后这是我们的关键词哦,切分呢,肯定不能用Li空格切分了,对吧,得调用咱们的什么。你看啊,这样,我把这个注释在这,它呢用的是split进行切分,切分完之后呢,把一个一个的词用connect的方式给它进行一个输出。
31:02
对吧,咱们呢,肯定不能用它进行切分,咱们得用什么。咱们得用。分词器对吧,就刚才我们写好的这个工具类啊,那我们的工具类叫keyword。点,然后呢,Str给我们的数据对吧?二加V得到一个。集合,接下来呢?对这个集合进变利立点负循环。这里边呢,是一个一个的word对吧,接下来我们就把这个word进行输出,模仿它来写就行了。呃,S没有SS.las也不需要,因为它官方例子呢,是word后面还有个Les。咱们只有一个word这一个列对吧,所以呢,我们不需要两个,而且呢,咱们也不叫S,咱们叫word。这样写就行了,好,那这边有异常,那这是具体的我们这个函数了,那这个异常我们要处理一下了,对吧,这属于工具类的调用了啊好好的要回车,然后呢。用try catch进行一个包裹,哎,那这个呢,我把它写到这里边。
32:05
如果说抓到异常了。怎么办?抓到一场说明什么问题啊?切词切不了。对吧,那这样切词切不了,那怎么办呢?咱们这样写connect,诶肉点of。SK。对吧,既然你切不了词,我抓到异常之后,我就把你整体做输出。可以吧,比如说我现在呢,有一个很奇怪的。乱七八糟的一个东西切不了对吧,切词报错,报错呢,我就把它当做一个整体,因为我切不出来呀,那怎么办?那我只能当做一个什么整体来做这个事情,OK吧,大家能理解哈,这个事情。那这个比较简单对吧,由于我们已经写好了这个工具类了,哎,直接切词,切完之后呢,把这个词一个一个的输出就好了,这样就达到了我们这个效果了,那到这块为止呢,咱们自定义的。
33:00
函数也已经写完了,还是比较简单的,对吧。
我来说两句