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也可以同时对多个事件流进行查询,即join,但是必须对每个事件流设置别名。例如:
// 当老师的id和学生的id相同时,查询学生的姓名和老师的姓名 select s.name, t.name from Student.win:time(10) as s, Teacher.win:time(10) as t where s.id=t.id
如果想查询Student或者Teacher,则EPL改写如下:
select s.* as st, t.* as tr from Student.win:time(10) as s, Teacher.win:time(10) as t where s.id=t.id
如果想要查询的属性只有存在于一个事件,那么可以不用"别名.属性名",但是最好还是带上别名,万一哪天另一个事件流多了一个一样的属性,那时候不需要修改EPL也可以使用。
4.insert和remove事件流
Esper对于事件流分输入和移出两种,分别对应监听器的两个参数newEvents和oldEvents,关于监听器的内容可参看前面章节中的事件模型。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之后,变化就更加多样了。
相关推荐
本篇文章将基于《esper语法pdf版(下)》的部分内容展开详细介绍,重点聚焦于API参考章节,特别是第13章的内容。Esper是一种事件处理语言和引擎,用于处理实时数据流中的复杂事件。本文将对Esper的主要接口进行深入...
4. **声明事件模式**: 使用Esper的SQL-like语法`EPL(Esper Programming Language)`来定义事件模式。例如,我们可以定义一个模式,当连续两个交易的股票价格上升时触发通知: ```sql create continuous query ...
EPL语法与SQL相似,但增加了对时间窗口、事件序列和状态变化的支持,这使得它在实时分析和决策制定中非常强大。 例如,一个简单的EPL语句可能是: ```sql select * from Event where price > 100 ``` 这条语句会...
1. `esper-5.2.0.jar`:这是Esper的核心库,包含了Esper的所有核心类和接口,如EPServiceProvider、EPL(Esper的SQL方言)语法等。开发者通过这个JAR文件可以直接在应用程序中使用Esper进行事件处理。 2. `antlr-...
1. **EPL 语言**:EPL 提供了丰富的语法来定义事件流、窗口、聚合、条件以及触发器。例如,可以创建一个简单的 EPL 语句来检测连续两个事件的时间间隔,或者更复杂的模式如“匹配任何三个连续递增的数字”。 2. **...
理解 Esper 的核心概念,熟练掌握 EPL 语法,以及合理利用窗口和监听器机制,可以帮助我们构建出高效、智能的实时数据处理系统。在实际应用中,还可以结合其他框架如 Spring,以更方便地集成 Esper 到现有的 Java ...
Esper的运行依赖于一些第三方库,如ANTLR用于解析模式和EPL语法,CGLIB用于代码生成,Apache Commons Logging用于日志处理,而在构建和测试阶段还需要JUnit单元测试框架和MySQL连接库。此外,Esper允许在应用启动前...
开发和部署EsperDist时,开发者需要掌握Java编程、Esper API、EPL语法以及分布式系统原理,如Apache ZooKeeper(用于协调集群状态)、Hadoop或Kafka(可能作为数据输入/输出接口)。同时,了解如何优化Esper的性能,...
### Esper官网文档中英文对照401-600页:用户自定义函数与事件处理 #### 一、用户自定义函数(User-Defined Functions) 在Esper中,用户自定义函数(User-Defined Functions, UDFs)允许开发人员扩展Esper的功能,...
EPL 的语法类似于 SQL,但针对时间序列和事件数据进行了优化,可以用于实时监控、报警、交易分析等场景。 接下来,我们关注如何集成 EPL 和 Storm。压缩包包含两个主要目录:`examples` 和 `lib`。`lib` 目录下的 ...