中秋三天,说闲也不闲,调调工作的代码,倒还解决不少问题。不过也是因为最近工作忙的缘故,Esper被我冷落不少日子了,趁着今天最后一天,赶紧写一篇出来。

从上一篇开始说EPL的语法,主要是关于注解的。今天来说说比较常用的语法,Select Clause和From Clause。这个两个可以说是写EPL必备,要想得到事件流的处理结果,基本上就靠他们俩了(Pattern除外)。今天的内容比较简单,还请各位同学牢记,以免以后应用的时候花时间看文档或者我的文章。

Select Clause

1.查询事件流的所有属性及特定属性

EPL的select和SQL的select很相近,SQL用*表示查询表的所有字段,而EPL用*表示查询事件流的所有属性值。SQL查询某个字段名,直接在select后跟字段名就ok,EPL也是将要查询的属性名放在select之后。若查多个属性值,则用逗号分割。和SQL一样,EPL查询属性也可以设置别名。示例如下:

// EPL:查询完整的User对象
select * from User
// 获取User对象
User u = newEvent.getUnderlying(); // EPL:查询User的name和id,id别名为i
select name, id as i from User
// 获取name和id
String name = (String)newEvent.get("name");
int id = (Integer)newEvent.get("i");

这里要注意,如果查询的是一个完整对象,需要调用getUnderlying()方法,而get方法是针对确定的属性名或者别名。另外*是不能设置别名的。

2.表达式

除了查询完整对象和特定属性,EPL还支持属性值的计算,以计算后的值作为结果返回,并且也能设置别名。这个计算的式子就是表达式。例如:

// 计算长方形的面积(长乘以宽)
select length * width as area from Rectangle

除了简单的加减乘除,还可以利用事件流对象的某个方法。例如:

// 计算长方形的面积(长乘以宽)
select r.getArea(r.length,r.width) as area from Rectangle as r select r.getArea() as area from Rectangle as r
// Rectangle类
public class Rectangle
{
    private int length;
    private int width; /** 省略getter/setter方法 **/
// 外部传入参数计算面积
public int getArea(int l, int w){
return l*w;
} // 计算该对象的面积
public int getArea(){
return length * width;
}
}

如上所示,一个方法需要传参,另一个方法不需要,但是他会利用当前事件的length和width来计算面积。而且要注意的是事件流需要设置别名才能使用其方法,如:r.getArea()

如果Rectangle类里没有计算面积的方法,但是提供了一个专门计算面积的静态方法,表达式也可以直接引用。不过要事先加载这个包含方法的类。例如:

// 该类用于计算面积
public class ComputeArea{ public static int getArea(int length, int width){
return length*width;
}
} // 加载
epService.getEPAdministrator().getConfiguration().addImport(ComputeArea.class);
// 调用ComputeArea的getArea方法计算面积
select ComputeArea.getArea(length,width) from Rectangle

注意一定要是静态方法,不然没有实例化是没法引用的。

3.多事件流的查询

和SQL类似,EPL也可以同时对多个事件流进行查询,但是必须对每个事件流设置别名。例如:

// 当老师的id和学生的id相同时,查询学生的姓名和老师的姓名
select s.name, t.name from Student as s, Teacher as t where s.id=t.id

如果想查询Student或者Teacher,则EPL改写如下:

select s.* as st, t.* as tr from Student as s, Teacher as t where s.id=t.id

如果想要查询的属性只有存在于一个事件,那么可以不用"别名.属性名",但是最好还是带上别名,万一哪天另一个事件流多了一个一样的属性,那时候不需要修改EPL也可以使用。

4.insert和remove事件流

Esper对于事件流分输入和移出两种,分别对应监听器的两个参数newEvents和oldEvents,关于监听器的内容可参看《Esper学习之三:进程模型》。newEvents通常对应事件的计算结果,oldEvents可以理解过上一次计算结果。默认情况下,只有newEvents有值,oldEvents为null。如果需要查看oldEvents,则需要使用一个参数。例如:

select rstream * from User

如果使用了该参数,则会将上一次计算结果放入newEvents内,而不是oldEvents(以前我还以为这是一个bug,后面发现手册上官方明确就是newEvents,汗!)。并且无法获得当前的计算结果

select irstream * from User

如果使用了该参数,则会将当前的计算结果放入newEvents内,上一次的计算结果放入oldEvents内。

select istream * from User
// 等同于
select * from User

如果使用了该参数,则会将当前的计算结果放入newEvents内,并且无法获得上一次的计算结果。同时该参数也是默认参数,可不写。

如果想修改默认参数,需要调用配置接口修改配置。

5.Distinct

distinct的用法和SQL一样,放在需要修饰的属性或者*前即可。例如:

select distinct * from User.win:time(3 sec)

6.查询指定引擎的处理结果

除了上述所说的一些特点外,select还可以针对某个引擎进行查询。因为引擎都有自己的URI,所以可以在select句子中增加URI标识来指定查询哪一个引擎的事件处理情况。例如:

// 引擎URI为Processor
select Processor.MyEvent.myProperty from Processor.MyEvent

From Clause

1.语法介绍

From的语法不难,主要内容是针对事件流的处理。包括事件流过滤,事件流的维持等等。语法如下:

from stream_def [as name] [unidirectional] [retain-union | retain-intersection] [, stream_def [as stream_name]] [, ...]

// 事件流
event_stream_name [(filter_criteria)] [contained_selection] [.view_spec] [.view_spec] [...]

unidirectional,retain-union,retain-intersection,contained_selection,view_spec这几个关键字因为涉及到view的知识,所以这里没法讲解。待学完view之后再来回顾这几个参数会很容易理解的。下面讲讲怎么过滤事件流

2.事件流过滤

2.1.事件属性过滤

事件流过滤通常情况都是对其中某个或多个属性加以限制来达到过滤的目的。注意,过滤表达式是紧跟在事件流名称之后而不是别名之后。例如:

// 只有age大于10的User对象才可查询到name值
select name from User(age>10) as user
// 当name=“luonanqin”时,可获得其age值
select age from User(name="luonanqin") // 错误写法
select name from User as user(age>10)

过滤表达式写法多种多样,可以用符号,又或者使用and,or,between等逻辑语言。例如:

// 查询年龄大于15小于18的学生的姓名
select name from Student(age between 15 and 18)
// 等同于
select name from Student(age >= 15 and age <= 18)
// 等同于
select name from Student(age >= 15, age <= 18)

看以看到,过滤表达式写法很多,并且多个表达式同时作用于一个事件流,用逗号连接即可。如果说满足其中一个条件即可,则需要用or连接。

2.2.过滤范围

刚才说到过滤表达式使用的符号很多,总结下来基本上有<, >, <=, >=, =, !=, between, in, not in, and, or, [ ], ( )。这里主要说下between,in,( ),[ ]

between……and……

和SQL的between……and……意思一样,是一个闭区间。比如说between 10 and 15,中文语义为10到15之间并包含10和15.

( )

表示一个开区间,语法为(low:high)。如(10:15),表示10到15之间,并且不包含10和15

[ ]

表示一个闭区间,语法为[low:high]。如[10:15],表示10到15之间,并且包含10和15

( )和[ ]可以混合用。比如[10:15)或者(10:15]

in

配合( )和[ ]进行使用,表示值在某个范围内。比如:

select name from User(age in [10:15))

相应的,not in表示不在此范围内。

以上都是针对数字的例子,in和not in同样可以作用于字符串。比如:

select age from User(name in ('张三', '李四'))

2.3 静态方法过滤

除了上面说的这些符号以外,类似于select子句中使用的静态方法,过滤表达式中也可以使用,但是返回值必须为布尔值,不然会报错。例如:

// 判断总数是否等于0
public class IsZero
{
public static boolean isZero(int sum)
{
return sum==0;
}
}
// 加载
epService.getEPAdministrator().getConfiguration().addImport(IsZero.class);
// 查询没有钱的用户的name值(User包含name和money属性)
select name from User(IsZero.isZero(money))

事件流的过滤并不能弄得很复杂,他有一下几个限制:

1. 要过滤的属性只能是数字和字符串。

2. 过滤表达式中不能使用聚合函数。

3. “prev”和“prior”函数不能用于过滤表达式(暂且不考虑这是什么)

Select和From的基础内容基本上就是上面所说的。当学过后面的章节之后,select和from可以写得很复杂,才能支持更为复杂的业务需求。特别是学过view和一些event function之后,变化就更加多样了。下一篇将讲解别的Clause,敬请期待。

Esper学习之六:EPL语法(二)的更多相关文章

  1. Esper学习之十二:EPL语法(八)

    今天的内容十分重要,在Esper的应用中是十分常用的功能之一.它是一种事件集合,我们可以对这个集合进行增删查改,所以在复杂的业务场景中我们肯定不会缺少它.它就是Named Window. 由于本篇篇幅 ...

  2. Esper学习之十一:EPL语法(七)

    上一篇说到了EPL如何访问关系型数据库这种数据源,实际上别的数据源,比如:webservice.分布式缓存.非关系型数据库等等,Esper提供了统一的数据访问接口.然后今天会讲解如何创建另外一种事件类 ...

  3. Esper学习之五:EPL语法(一)

    上篇说到了Esper的Context,要是不了解的同学请参看<Esper学习之四:Context>,看过的同学如果还是不理解的话可以给我评论,我将会尽可能的解答.之前有些同学问我Conte ...

  4. Esper学习之九:EPL语法(五)

    本篇的内容主要包括了Subquery(也就是子查询)和Join,内容不少,但是不难,基本上和sql差不太多. 1.Subquery EPL里的Subquery和sql的类似,是否比sql的用法更多我不 ...

  5. Esper学习之七:EPL语法(三)

    1.Aggregation 和SQL一样,EPL也有Aggregation,即聚合函数.语法如下: aggregate_function([all|distinct] expression) aggr ...

  6. Esper学习之十五:Pattern(二)

    上一篇开始了新一轮语法——Pattern的讲解,一开始为大家普及了几个基础知识,其中有说到操作符.当时只是把它们都列举出来了,所以今天这篇就是专门详解这些操作符的,但是由于篇幅限制,本篇先会讲几个,剩 ...

  7. web前端学习python之第一章_基础语法(二)

    web前端学习python之第一章_基础语法(二) 前言:最近新做了一个管理系统,前端已经基本完成, 但是后端人手不足没人给我写接口,自力更生丰衣足食, 所以决定自学python自己给自己写接口哈哈哈 ...

  8. Esper学习之四:Context

    上周末打球实在太累了,就没来得及更新,只是列了个提纲做做准备,发现Context还是有很多内容的.结果也花了不少时间才写完,所以这篇需要各位慢慢消化,并且最好多写几个例子加深理解. 如果有不了解Esp ...

  9. Esper学习之三:进程模型

    之前对Esper所能处理的事件结构进行了概述,并结合了例子进行讲解,不清楚的同学请看Esper学习之二:事件类型.今天主要为大家解释一下Esper是怎么处理事件的,即Esper的进程模型. 1.Upd ...

随机推荐

  1. [重磅] 让HTML5达到原生的体验 系列之中的一个 避免切页白屏

    非常多人都想.甚至曾使用HTML5开发跨平台App.而且想达到原生App的体验. 最后的结果都是无奈的放弃.HTML5貌似美好,但坑太多.想做到原生App的体验差点儿不可为. 也曾有过著名的faceb ...

  2. mmc加工配套问题

    题目如下,本题还有其它解.

  3. [Immutable.js] Converting Immutable.js Structures to Javascript and other Immutable Types

    Immutable.js provides several conversion methods to migrate one structure to another. Each Immutable ...

  4. 数据库的四种语言(DDL、DML、DCL、TCL)

    1.DDL (Data Definition Language )数据库定义语言 statements are used to define the database structure or sch ...

  5. char值码对应大全

    Char("0") 为0的字符Char("1") Char("2") Char("3") Char("4&qu ...

  6. aspx调用webmethod

    [WebMethod] public static string CheckLogin(string user, string pwd) { pwd = FormsAuthentication.Has ...

  7. (转)Should I use char** argv or char* argv[]

      As you are just learning C, i recommend you to really try to understand the differences between ar ...

  8. Android 开发技术流程

    1.网络连接通信 HttpClient 类通信(见<第一行代码> 郭霖2014.8月第一版P385) Android Asynchronous Http Client  (见  http: ...

  9. JDK动态代理例子

    JDK动态代理的代理类必须实现于接口.如果要代理类,则使用CGLIB代理. 先定义一个接口: public interface Character { public void show(); } 接着 ...

  10. XMLHttpRequest基础知识

    XMLHttpRequest 发送请求的两个重要方法:open(method,url,async)——参数:请求方式.请求地址.请求同步/异步:send(string)——参数:使用POST方式时,填 ...