Esper學習之六:EPL語法(二)

 從上一篇開始說EPL的語法,主要是關於註解的。今天來說說比較常用的語法,Select Clause和From Clause。這個兩個可以說是寫EPL必備,要想得到事件流的處理結果,基本上就靠他們倆了(Pattern除外)。今天的內容比較簡單,還請各位同學牢記,以免以後應用的時候花時間看文檔或者我的文章。


Select Clause

1.查詢事件流的所有屬性及特定屬性

EPL的select和SQL的select很相近,SQL用*表示查詢表的所有字段,而EPL用*表示查詢事件流的所有屬性值。SQL查詢某個字段名,直接在select後跟字段名就ok,EPL也是將要查詢的屬性名放在select之後。若查多個屬性值,則用逗號分割。和SQL一樣,EPL查詢屬性也可以設置別名。示例如下:

[plain] view plaincopy
  1. // EPL:查詢完整的User對象  
  2. select * from User  
  3. // 獲取User對象  
  4. User u = newEvent.getUnderlying();  
  5.   
  6. // EPL:查詢User的name和id,id別名爲i  
  7. select name, id as i from User  
  8. // 獲取name和id  
  9. String name = (String)newEvent.get("name");  
  10. int id = (Integer)newEvent.get("i");  
這裏要注意,如果查詢的是一個完整對象,需要調用getUnderlying()方法,而get方法是針對確定的屬性名或者別名。另外*是不能設置別名的。


2.表達式

除了查詢完整對象和特定屬性,EPL還支持屬性值的計算,以計算後的值作爲結果返回,並且也能設置別名。這個計算的式子就是表達式。例如:

[plain] view plaincopy
  1. // 計算長方形的面積(長乘以寬)  
  2. select length * width as area from Rectangle  
除了簡單的加減乘除,還可以利用事件流對象的某個方法。例如:

[plain] view plaincopy
  1. // 計算長方形的面積(長乘以寬)  
  2. select r.getArea(r.length,r.width) as area from Rectangle as r  
  3.   
  4. select r.getArea() as area from Rectangle as r  

[java] view plaincopy
  1. // Rectangle類  
  2. public class Rectangle  
  3. {  
  4.     private int length;  
  5.     private int width;  
  6.   
  7.     /** 省略getter/setter方法 **/  
  8.     // 外部傳入參數計算面積  
  9.     public int getArea(int l, int w){  
  10.         return l*w;  
  11.     }  
  12.   
  13.     // 計算該對象的面積  
  14.     public int getArea(){  
  15.         return length * width;  
  16.     }  
  17. }  

如上所示,一個方法需要傳參,另一個方法不需要,但是他會利用當前事件的length和width來計算面積。而且要注意的是事件流需要設置別名才能使用其方法,如:r.getArea()

如果Rectangle類裏沒有計算面積的方法,但是提供了一個專門計算面積的靜態方法,表達式也可以直接引用。不過要事先加載這個包含方法的類。例如:

[java] view plaincopy
  1. // 該類用於計算面積  
  2. public class ComputeArea{  
  3.       
  4.     public static int getArea(int length, int width){  
  5.         return length*width;  
  6.     }  
  7. }  
  8.   
  9. // 加載  
  10. epService.getEPAdministrator().getConfiguration().addImport(ComputeArea.class);  
[plain] view plaincopy
  1. // 調用ComputeArea的getArea方法計算面積  
  2. select ComputeArea.getArea(length,width) from Rectangle  
注意一定要是靜態方法,不然沒有實例化是沒法引用的。


3.多事件流的查詢

和SQL類似,EPL也可以同時對多個事件流進行查詢,但是必須對每個事件流設置別名。例如:

[plain] view plaincopy
  1. // 當老師的id和學生的id相同時,查詢學生的姓名和老師的姓名  
  2. select s.name, t.name from Student as s, Teacher as t where s.id=t.id  
如果想查詢Student或者Teacher,則EPL改寫如下:

[plain] view plaincopy
  1. 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,則需要使用一個參數。例如:

[plain] view plaincopy
  1. select rstream * from User  
如果使用了該參數,則會將上一次計算結果放入newEvents內,而不是oldEvents(以前我還以爲這是一個bug,後面發現手冊上官方明確就是newEvents,汗!)。並且無法獲得當前的計算結果

[plain] view plaincopy
  1. select irstream * from User  
如果使用了該參數,則會將當前的計算結果放入newEvents內,上一次的計算結果放入oldEvents內。

[plain] view plaincopy
  1. select istream * from User  
  2. // 等同於  
  3. select * from User  
如果使用了該參數,則會將當前的計算結果放入newEvents內,並且無法獲得上一次的計算結果。同時該參數也是默認參數,可不寫。

如果想修改默認參數,需要調用配置接口修改配置。


5.Distinct

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

[plain] view plaincopy
  1. select distinct * from User.win:time(3 sec)  

6.查詢指定引擎的處理結果

除了上述所說的一些特點外,select還可以針對某個引擎進行查詢。因爲引擎都有自己的URI,所以可以在select句子中增加URI標識來指定查詢哪一個引擎的事件處理情況。例如:

[plain] view plaincopy
  1. // 引擎URI爲Processor  
  2. select Processor.MyEvent.myProperty from Processor.MyEvent  

From Clause

1.語法介紹

From的語法不難,主要內容是針對事件流的處理。包括事件流過濾,事件流的維持等等。語法如下:

[plain] view plaincopy
  1. from stream_def [as name] [unidirectional] [retain-union | retain-intersection] [, stream_def [as stream_name]] [, ...]  
  2.   
  3. // 事件流  
  4. 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.事件屬性過濾

事件流過濾通常情況都是對其中某個或多個屬性加以限制來達到過濾的目的。注意,過濾表達式是緊跟在事件流名稱之後而不是別名之後。例如:

[plain] view plaincopy
  1. // 只有age大於10的User對象纔可查詢到name值  
  2. select name from User(age>10) as user  
  3. // 當name=“luonanqin”時,可獲得其age值  
  4. select age from User(name="luonanqin")  
  5.   
  6. // 錯誤寫法  
  7. select name from User as user(age>10)  
過濾表達式寫法多種多樣,可以用符號,又或者使用and,or,between等邏輯語言。例如:

[plain] view plaincopy
  1. // 查詢年齡大於15小於18的學生的姓名  
  2. select name from Student(age between 15 and 18)  
  3. // 等同於  
  4. select name from Student(age >= 15 and age <= 18)  
  5. // 等同於  
  6. 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

配合( )和[ ]進行使用,表示值在某個範圍內。比如:

[plain] view plaincopy
  1. select name from User(age in [10:15))  
相應的,not in表示不在此範圍內。

以上都是針對數字的例子,in和not in同樣可以作用於字符串。比如:

[plain] view plaincopy
  1. select age from User(name in ('張三', '李四'))  


2.3 靜態方法過濾

除了上面說的這些符號以外,類似於select子句中使用的靜態方法,過濾表達式中也可以使用,但是返回值必須爲布爾值,不然會報錯。例如:

[java] view plaincopy
  1. // 判斷總數是否等於0  
  2. public class IsZero  
  3. {  
  4.     public static boolean isZero(int sum)  
  5.     {  
  6.         return sum==0;  
  7.     }  
  8. }  
  9.   
  10. <pre name="code" class="java">// 加載  
  11. epService.getEPAdministrator().getConfiguration().addImport(IsZero.class);</pre>  
[plain] view plaincopy
  1. // 查詢沒有錢的用戶的name值(User包含name和money屬性)  
  2. select name from User(IsZero.isZero(money))  

事件流的過濾並不能弄得很複雜,他有一下幾個限制:

1. 要過濾的屬性只能是數字和字符串。

2. 過濾表達式中不能使用聚合函數。

3. “prev”和“prior”函數不能用於過濾表達式(暫且不考慮這是什麼)


       Select和From的基礎內容基本上就是上面所說的。當學過後面的章節之後,select和from可以寫得很複雜,才能支持更爲複雜的業務需求。特別是學過view和一些event function之後,變化就更加多樣了。下一篇將講解別的Clause,敬請期待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章