00:00
来呢,给大家再讲一讲data stream API里边另外一个连接两条流的操作,那就是所谓的draw影,呃,Draw影的话其实是属于电API里边一个比较特殊的操作,大家会发现就是后面我们会看到啊,它的使用其实是比较有局限的,就是这里面API调用是固定的一个流程,每一步必须是这样去调,对吧?能调的这个方法灵活度没有那么高,但是呢,在有一些场景下,比较简单的两条流的连接还是比较实用的,这里给大家稍微的做一个讲解,就是首先draw影分成两大类。一大类叫做window join,另外一大类叫做interval join,字面理解的话就是一个叫窗口连接,另外一个叫呃,间隔连接,或者叫区间连接啊,这样这到底是一个什么概念呢?一个一个看,我们首先看这个所谓的窗口连接啊,Window draw什么意思呢?大家看这个data stream API里边啊,我们直接看到这个data streamam的源码里,里边有一个方法就叫做draw,对吧?所以我们其实是可以用一个data stream直接点draw,然后去连接另外一条流的,这个是完全没没问题的。
01:16
那得到的是一个什么数据类型呢?大家注意是一个join the streams,这里边就像我们那个collected streams一样,是不是有两个泛型啊,这看起来差不多对吧?然后我们得到那个connected streams呢?是后边一国两制啊,就是你如果扣map的话,是MAP1MAP2,如果是扣process的话,那就是这个process element1 process element2,那现在这个join the stream接下来又能调什么方法呢?大家看到它里边也是INPUT1INPUT22个流对吧,那里边的能调的方法,大家看它只能调一个方法,就叫做where。顾名思义,大家其实能想到where是要干什么呀,对,大家看里边这个参数就知道了,是不是要给一个case select,是不是要指定当前的连接条件啊?那就是我们说的,你不是要做draw语吗?要做连接吗?我们join语的时候,表连接的时候是不是也有where什么等于什么呀?对吧,总得有一个连接条件,所以这里边其实就是要给这个连接,连接条件首先是一个提取K的过程。
02:21
那大家想这里边提取的是哪个流里边的K呢?这只有第一个流里的K对吧?大家看这里边的数据类型是不是T1啊k Le是T1K,那第二个第二个流里边难道不提取K吗?我们要连接条件肯定是第一个K等于第二个K嘛,哎,所以大家继续往后看,不要着急,下一步这个where得到的结果呢,必须就是一个V类型,大家看得到是一个where类型,对吧?那这个where类型其实是drawing the streams里边的一个子类内部类对吧?这个内部类呢,只有一个方法,接下来也只有一个方法,叫做equal to,大家从四面理解的话,是不是就是where,呃,那个K是什么?然后equal to等于另外一条流里边的什么?
03:10
这是不是就是我们写那个表连接的时候,Where什么等于什么呀,对吧啊,Where表一的ID等于表二的ID对吧?啊,就是这样的一个过程嘛,所以这里面得到的这个这里边又是一个key select,这里就是第二条流里的的K的选择了,然后得到的这个类型呢,直接就叫做e two,这又是里边的一个内部类。然后接下来这个类又能调什么方法呢?只能调一个方法,就是window,就是开窗,所以为什么说这个就叫做window draw drawing呢?窗口连接呢,因为到最后你调来调去最后只能开窗,对吧?就是首先把两条连接起来,给一个连接,按照K啊给一个连接条件,后边就只能是开窗口去做操作。然后开窗口,这里面的操作呢,你看到里边传的是什么。
04:00
Window a sign,这跟之前我们讲到的那个窗口分配器是不是一模一样啊,所以这里面你就可以给一个啊,就是。Tumbling slide,呃呃,Slide的这个就是像我们这个滚动时间窗口对吧,滑动时间窗口都可以去在这里边单独去做定义了,对吧,像我们那个tumbling even time window啊,或者是这个呃,Sliding,呃,这个processing time window对吧?各种时间语义不同的窗口都可以去指定,然后这里在得到的这个结果呢。大家注意啊,这个之前我们开窗得到的是一个window stream,对吧,这个可不是,这个开窗得到的叫做with window还是里边的一个内部类,当然这是一个static,静态的一个内部类,对吧?它里边能调的方法。大家会看到这里边是不是就又是有一些可选的API可调啊,诶,Alo late熟悉不熟悉,是不是还是之前我们那个window的可选API啊,它调这个allow lateness大家看得到的是不是还是window window类型不变对吧?另外还有大家比较熟悉的avi移熟器是不是可选,因为里边得到的还是with window对吧?另外这个trigger是不是还是这个呀,With window对吧?哎,那另外呃,还有就是除了这个getloud lateness,还有get,就是get的一些方法之外,最终我们不是说指定窗口分配器开窗之后一定要给一个窗口函数做计算吗?啊,那除了这些可选API之外,那个最终的那个计算在哪呢?大家看到了,是不是只有一个方法是做计算的呀?
05:35
Apply对吧,所以这里面就只能调一个apply方法。然后apply方法里边传的是一个drawing function,然后它就是表示当前窗口里面做什么连接计算,最后得到一个data string,对吧?诶,这就是这样的一个流程。那draw function的话,这是一个接口,你看这个join function是啥?这不就是第一个元素,第二个元素都放在这儿,对吧,要连接的这两个元素都给都给都给你了,那接下来你就是该怎么整合怎么整合,最后得到一个输出的out类型就完了。
06:09
这就是连接对吧?啊,所以整体来讲是非常简单的,它的使用可以说也就是必须按照这个流程来。总结一下的话,大家可以看一下这个官网上的代码啊,大家看这个过程就是什么?就这个流程对吧?写出来就是这样,首先一个data stream drawing,另外一个data stream,接下来where指定第一条流里面的K是什么?Equal to第二个流里面的K,这相当于这两步就是做了一个连接的条件定义对吧?啊,就是什么等于什么,然后接下来就是点window.apply只能这么去做啊,那我们接下来具体还是看一个实际的例子吧,啊,那大家看实际来划分的话,那是不是就划分按照窗口的类型不一样,就分成了滚动窗口连接,滑动窗口连接,还有会话窗口连接啊呃,这其实就是这么几种不同的定义啊,那我们就看一个具体的例子,滚动窗口连接。
07:07
大家看一下这个滚动窗口连接怎么去写啊,直接比方说我们现在有两条流,两条流一条流叫做orange stream,另外一条流叫做green stream,就是一条成流,一条绿流,对吧?然后接下来乘流去撞,用绿流,然后where指定e to指定后面这个window开窗的时候,你看这里边怎么给的。这里边就没有我们当时写的那个简写方式了,之前我们是不是有那个time木window count window有简写啊,一般我们调的时候都那么调,现在它有那个简写的time window吗?没有,这个API大家在原版里面看到了,对吧?所以里边是不是就必须用之前给大家说过的这个底层的window啊,S这种写法呀,还记得这个吧,对吧?当前这是tumbling even time Windows,这是不是就是一个滚动的事件时间窗口?指定它的大小的时候,是不是要来一个点of呀,然后里边传一个时间对吧?滚动时间窗口,然后后面就是一个apply apply里边必须传一个draw function啊,当然这里边大家看源码里边不一定非得是draw function啊,就是除了直接传一个draw function之外,是不是还可以传一个flat draw function啊,顾名思义这个跟draw function的区别在哪里?对,大家看是不是除了呃这里边有这两个参数,两两条流里面的数据啊,作为参数传入,它是不是直接没有返回类型啊,那返回值用什么来输出呢?对,大家看是不是out.collect啊,跟我们之前讲的那个map Fla map是一样的,对吧?啊,所以这就是关于这个窗口连接啊,窗口撞一个过程,那大家看这里边这个装function,它的做法非常的简单粗暴,拿到了first和SECOND2条流里面的数据,它是不是直接返回了一个string啊?
08:54
直接把这个逗号连接直接放在这儿就完事了,对吧。啊,这是这是关于这个滚动呃,窗口连接啊好,刚才这个图没刷出来,大家看一下这个图对应的啊,到底是一个什么原则呢?这个窗口连接的时候,其实就是还是按照我们定义的那个窗口大小去把数据做一个划分,现在是两条流,那大家看这个绿流成流,各自各自定义各自的对不对啊放在这里啊,然后大家看到这里边的这个对应里边的这个数据啊,就相当于是当前数据对应的那个时间戳。
09:30
大家看下边我们不是定义了这个滚动时间窗口的大小就是两毫秒嘛,对吧,大家看它定义的是两毫秒啊,所以这个如果是时间戳的话,当然就是毫秒数了,两毫秒一个一个滚动窗口,那其实是不是应该是零到二,这里边是包括零不包括二对吧?所以大家看是不是零一都属于第一个窗口,二就属于下一个窗口了,对吧?两毫秒一个滚动窗口嘛,然后我们连接的时候是怎么连接呢?其实非常简单,就是按照窗口把这个两条流里的数据都做了划分之后,属于同一个窗口,我们知道窗口就是桶嘛,属于同一个桶里边的两条流里边的数据直接做一个笛卡耳机。
10:14
第二级大家知道就可以类似于是交叉连接对吧,就是两两都做一个配对,所以你看这里边连接的效果就是什么呢?第一个窗口里边零到两秒,它连接的效果就是。00011011对吧,D2基两两都匹配在一起,所以后边调用这个apply方法的时候,呃,就这里边的这个apply,然后里边调用这个状语方法的时候,大家看到是什么,是不是每一对。First和second,就是每一个绿流里的数据和城流里边数据合在一起的这一对都会调用一次照明方法呀,所以大家看这其实就是它输出的结果对吧?因为最后我们不是逗号连接输出了一个string吗?这就是输出的00011011对吧。
11:01
然后从后边的这个输出结果上看,大家能看出来这是谁照应谁嘛,啊,当然在代码里面我们刚才已经看到了是吧,从这个结果大家其实也能看出来这是谁照应谁,23332333是不是城流里面的数据在前啊,诶,所以后边的那个应一应二啊,First和second那个顺序也是谁join应谁谁,就是第一个,第一个流由跟我们那个connect streams里边的定义是不是也是一样的呀?啊所以这个其实都非常理解,主要的原理就是大家知道在一个窗口里边收集到的两条流里边的所有数据,做一个迪卡尔级两两连接,他们配对之后的每一对都直接去调,这里边的这个装function里边的这个撞语方法就可以了。啊,这就是窗口连接啊,呃,Window draw这个过程。那当然了,后边这个滑动窗口连接和会画窗口连接其实都一样,它们的区别就在于就是这个窗口长什么样对吧?然后只要窗口划分好了,对应的数据都已经都知道它属于哪个窗口了,那接下来我们窗口的操作是不是就是把属于这个窗口里边的两条流里的所有数据,笛卡耳机对吧?两两配对,然后去做输出就完事了啊,所以整个窗口连接还是比较简单的。
我来说两句