关于EPL,已经写了三篇了,预估计了一下,除了今天这篇,后面还有5篇左右。大家可别嫌多,官方的文档对EPL的讲解有将近140页,我已经尽量将废话都干掉了,再配合我附上的例子,看我的10篇文章比那140页英文文档肯定舒服多了吧。也请各位原谅我一周一篇的速度,毕竟我还要学习,生活,工作,一个都不能少。
今天讲解的内容包括三块:Order by,Limit,Insert into。大家会SQL的应该很熟悉这三个东西,前两个比较简单,Insert into会有一些差别,篇幅也相对多些。
1.Order by
EPL的Order by和SQL的几乎一模一样,作用都是对输出结果进行排序,但是也有一些需要注意的地方。语法如下:
expreession表示要排序的字段,asc表示升序排列(从小到大),desc表示降序排列(从大到小)。举个例子:
a. 如果不特别说明是升序还是降序,默认情况下按照升序排列。
b. 如果order by的子句中出现了聚合函数,那么该聚合函数必须出现在select的子句中。
c. 出现在select中的expression或者在select中定义的expression,在order by中也有效。
d. 如果order by所在的句子没有join或者没有group by,则排序结果幂等,否则为非幂等。
2. Limit
Limit在EPL中和在SQL中也基本一样,不过SQL中是用具体的数字来表示限制范围,而EPL可以是常量或者变量来表示限制范围。语法如下:
offset_count表示在当前结果集中跳过n行然后再输出,同样也可以是一个整型变量。如果不使用此参数,则表示跳过0行,即从第一行输出。举例如下:
row_count为负数,则无限制输出,若为0,则不输出。当row_count是变量表示并且变量为null,则无限制输出。
offset _count是不允许负数的,如果是变量表示,并且变量值为null或者负数,则EPL会把他假设为0。
3. Insert into
3.1 简单用法
EPL的Insert into和SQL的有比较大的区别。SQL是往一张表里插入数据,而EPL是把一个事件流的计算结果放入另一个事件流,然后可以对这个事件流进行别的计算。所以Insert into的一个好处就是可以将是事件流的计算结果不断级联,对于那种需要将上一个业务的结果数据放到下一个业务处理的场景再适合不过了。除此之外,Insert into还有合并多个计算结果的作用。到这里相信大家已经对他越来越好奇了,不急,咱们先来看看语法:
event_stream_name定义了事件流的名称,在执行完insert的定义之后,我们可以使用select对这个事件流进行别的计算。
istream | irstream | rstream表示该事件流允许另一个事件的输入/输入和输出/输出数据能够进入(解释好像很绕。。一会儿看例子就能明白了)
property_name表示该事件流里包含的属性名称,多个属性名之间用逗号分割,并且用小括号括起来。
上面的说明可能不是很好理解,咱们先看个例子:
我个人推荐第二种写法,通过as设置的别名即为insert定义的事件流的属性,这样可以避免属性的个数不一致的错误。
刚才说了istream | irstream | rstream的用法,可能有点表述不清楚,这里看一个完整的例子。
如果不显示指定rstream,则insert into只允许istream的事件流进入Computer。如果指定为irstream,那么进入的和移除的Asus都会进入到Computer。
上面的例子都是指定了insert into里事件流会有什么属性,如果不指定会是什么结果呢?请看例句:
假设Asus中还包含其他的JavaBean,同样也可以将这个Bean的数据传递到另一个事件流中。例句如下:
3.2 Merge Event Stream
insert into除了接收一个流的事件,同时也支持多个流的合并。通俗一点来说,合并的流数据要一致才可以合并。而且在第一次定义insert的事件流以后,别的事件流想要被合并就必须和之前定义的属性数量和数据类型对应。举例如下:
3.3 Decorated Events
之前所见到的不是将事件流整体输入insert,就是将事件流的部分属性输入insert。实际上可以将事件流整体和事件流属性组成的复杂表达式一起放入insert。示例如下:
3.4 Event Objects Instantiated by insert into
前面的所有例子中,对于insert into的事件结构都是在insert子句中配合select子句进行定义的。如果我们想用已经定义好的事件结构是否可以呢?答案是肯定的。但是如果事件是javabean,并且事先没有注册到引擎,则需要insert子句中写上类的全名。例如:
因为事件结构是早就定义好的,所以在写select的时候就必须符合insert事件中的属性了,如果属性名称不一样需要使用as加上别名,一样的可以不用设置别名,且数据类型也要一一对应。例如:
String benzEpl = "select * from " + benz;admin.createEPL(cartToAutoEpl);EPStatement state1 = admin.createEPL(autoEpl);state1.addListener(new InstantiatePopulateListener());admin.createEPL(cartToBenzEpl);EPStatement state2 = admin.createEPL(benzEpl);state2.addListener(new InstantiatePopulateListener());EPRuntime runtime = epService.getEPRuntime();Car c1 = new Car();c1.setSize(1);c1.setName("car1");c1.setPrice(11);runtime.sendEvent(c1);Car c2 = new Car();c2.setSize(2);c2.setName("car2");c2.setPrice(22);runtime.sendEvent(c2);}}
对于Auto的JavaBean,我们可以发现它包含一个有参数的构造函数且没有属性对应的set方法,在carToAutoEpl中,select的内容并没有和属性名称对应起来。这种写法确实是正确的,正因为Auto中定了含参的构造函数,才使得select可以写的更随意。但是一定要记住,构造函数里的参数顺序一定要和select中的属性的数据类型对应起来,如果这里把name和size互换位置,必定报错!
对于Benz的JavaBean,可以看到每个属性都有对应的set方法,而没有含参的构造函数,所以select中属性的名称需要as来设置别名。当然,像benzEpl2那种写法,同样可以避免select中设置别名。
一句话总结,如果JavaBean中有含参的构造函数,EPL中不需要显示写出属性名称。如果没有构造函数,那么必须包含set方法,且select中要写出具体的属性。这几种写法各有各的好处,大家使用时可针对具体的情况选择性使用。
今天的内容总的来说是比较轻松的,insert into也算是今天的重点,希望大家好好学习,用处可是大大滴有哦。