esper.codehaus.org and espertech.comDocumentation
EPL provides enumeration methods that work with lambda expressions to perform common tasks on subquery results, named windows, event properties or inputs that are or can be projected to a collection of events, scalar values or objects.
Enumeration methods are stateless and the use of enumeration methods alone does not cause the engine to retain any events or other state (with the possible exception of short-lived caching of evaluation results).
A lambda expression is an anonymous expression. Lambda expressions are useful for encapsulating user-defined expressions that are applied to each element in a collection. This section discusses built-in enumeration methods and their lambda expression parameters.
Lambda expressions use the lambda operator =>
, which is read as "goes to" (->
may be used and is equivalent). The left side of the lambda operator specifies the lambda expression input parameter(s) (if any) and the right side holds the expression. The lambda expression x => x * x is read "x goes to x times x.".
Lambda expressions are also used for expression declaration as discussed in Section 5.2.8, “Expression Declaration”.
When writing lambdas, you do not have to specify a type for the input parameter(s) or output result(s) because the engine can infer all types based on the input and the expression body. So if you are querying an RFIDEvent, for example, then the input variable is inferred to be an RFIDEvent event, which means you have access to its properties and methods.
The term element in respect to enumeration methods means a single event, scalar value or object in a collection that is the input to an enumeraton method. The term collection means a sequence or group of elements.
The below table summarizes the built-in enumeration methods available:
Table 10.1. Enumeration Methods
Method | Result |
---|---|
aggregate(seed, accumulator lambda) |
Aggregate elements by using seed as an initial accumulator value and applying an accumulator expression. |
allof(predicate lambda) |
Return true when all elements satisfy a condition. |
anyof(predicate lambda) |
Return true when any element satisfies a condition. |
average() |
Computes the average of values obtained from numeric elements. |
average(projection lambda) |
Computes the average of values obtained from elements by invoking a projection expression on each element. |
countof() |
Returns the number of elements. |
countof(predicate lambda) |
Returns the number of elements that satisfy a condition. |
distinctOf() |
Returns distinct elements according to default hash and equals semantics. |
distinctOf(key-selector lambda) |
Returns distinct elements according using the key function provided. |
except(source) |
Produces the set difference of the two collections. |
firstof() |
Returns the first element. |
firstof(predicate lambda) |
Returns the first element that satisfies a condition. |
groupby(key-selector lambda) |
Groups the elements according to a specified key-selector expression. |
groupby(key-selector lambda, value-selector lambda) |
Groups the elements according to a key-selector expression mapping each element to a value according to a value-selector. |
intersect(source) |
Produces the set intersection of the two collections. |
lastof() |
Returns the last element. |
lastof(predicate lambda) |
Returns the last element that satisfies a condition. |
leastFrequent() |
Returns the least frequent value among a collection of values. |
leastFrequent(transform lambda) |
Returns the least frequent value returned by the transform expression when applied to each element. |
max() |
Returns the maximum value among a collection of elements. |
max(value-selector lambda) |
Returns the maximum value returned by the value-selector expression when applied to each element. |
maxby(value-selector lambda) |
Returns the element that provides the maximum value returned by the value-selector expression when applied to each element. |
min() |
Returns the minimum value among a collection of elements. |
min(value-selector lambda) |
Returns the minimum value returned by the value-selector expression when applied to each element. |
minby(value-selector lambda) |
Returns the element that provides the minimum value returned by the value-selector expression when applied to each element.. |
mostFrequent() |
Returns the most frequent value among a collection of values. |
mostFrequent(transform lambda) |
Returns the most frequent value returned by the transform expression when applied to each element. |
orderBy() |
Sorts the elements in ascending order. |
orderBy(key-selector lambda) |
Sorts the elements in ascending order according to a key. |
orderByDesc() |
Sorts the elements in descending order. |
orderByDesc(key-selector lambda) |
Sorts the elements in descending order according to a key. |
reverse |
Reverses the order of elements. |
selectFrom(transform lambda) |
Transforms each element resulting in a collection of transformed elements. |
sequenceEqual(second) |
Determines whether two collections are equal by comparing each element ( |
sumOf() |
Computes the sum from a collection of numeric elements. |
sumOf(projection lambda) |
Computes the sum by invoking a projection expression on each element. |
take(numElements) |
Returns a specified number of contiguous elements from the start. |
takeLast(numElements) |
Returns a specified number of contiguous elements from the end. |
takeWhile(predicate lambda) |
Returns elements from the start as long as a specified condition is true. |
takeWhile( (predicate, index) lambda) |
Returns elements from the start as long as a specified condition is true, allowing each element's index to be used in the logic of the predicate expression. |
takeWhileLast(predicate) |
Returns elements from the end as long as a specified condition is true. |
takeWhileLast( (predicate,index) lambda) |
Returns elements from the end as long as a specified condition is true, allowing each element's index to be used in the logic of the predicate expression. |
toMap(key-selector lambda, value-selector lambda) |
Returns a Map according to specified key selector and value-selector expressions. |
union(source) |
Forms a union of the input elements with source elements. |
where(predicate lambda) |
Filters elements based on a predicate. |
where( (predicate,index) lambda) |
Filters elements based on a predicate, allowing each element's index to be used in the logic of the predicate expression. |
The examples in this section come out of the domain of location report (aka. RFID, asset tracking etc.) processing:
The Item
event is a report of the location of a certain item. An item can be either a piece of luggage or a passenger.
The LocationReport
event contains a list of Item
items for which it reports location.
The Zone
event describes areas that items may move through.
The examples use example single-row functions for computing the distance (distance
) and for determining if a location falls within a rectangle (inrect
) that are not provided by the EPL language. These example UDF functions are not enumeration methods
and are used in EPL statements to provide a sensible example.
The Item
event contains an assetId
id, a (x,y) location
, a luggage
flag to indicate whether the item represents a luggage (true) or passenger (false), and the assetIdPassenger
that holds the asset id of the associated passenger when the item is a piece of luggage.
The Item
event is defined as follows (access methods not shown for brevity):
public class Item { String assetId; // passenger or luggage asset id Location location; // (x,y) location boolean luggage; // true if this item is a luggage piece String assetIdPassenger; // if the item is luggage, contains passenger associated ...
The LocationReport
event contains a list of Item
items for which it reports events.
The LocationReport
event is defined as follows:
public class LocationReport { List<Item> items; ...
The Zone
event contains a zone name
and (x1, y1, x2, y2) rectangle
.
The Zone
event is defined as follows:
public class Zone { String name; Rectangle rectangle; ...
The Location
object is a nested object to Item
and provides the current (x,y) location:
public class Location { int x; int y; ...
The Rectangle
object is a nested object to Zone
and provides a zone rectangle(x1,y1,x2,y2):
public class Rectangle { int x1; int y1; int x2; int y2; ...
The syntax for enumeration methods is the same syntax as for any chained invocation:
input_coll.enum_method_name( [method_parameter [, method_parameter [,...]]]) .[ [enum_method_name(...) [...]] | property_name]
Following the input_coll input collection (options outlined below), is the .
(dot) operator and the enum_method_name enumeration method name. It follows in parenthesis a comma-separated list of method parameter expressions. Additional enumeration methods can be chained thereafter. An event property name can follow for those enumeration methods returning an event-typed (non-scalar) element.
If the method parameter is a lambda expression with a single lambda-parameter, specify the lambda-parameter name followed by the =>
lambda operator and followed by the expression. The synopsis for use with a single lambda-parameter is:
method_parameter: lamda_param => lamda_expression
If the method parameter is a lambda expression with two or more lambda-parameters, specify the lambda parameter names in parenthesis followed by the => lambda operator followed by the expression. The synopsis for use with multiple lambda-parameters is:
method_parameter: (lamda_param [,lamda_param [,...]]) => lamda_expression
Generally for lambda expressions, the engine applies the lambda expression to each element in the input collection. The expression yields a result that, depending on the particular enumeration method, is used for aggregation, as a filter or for output, for example.
Let's look at an EPL statement that employs the where
enumeration method and a lambda expression. This example returns items that have a (x, y) location of (0, 0):
select items.where(i => i.location.x = 0 and i.location.y = 0) as zeroloc from LocationReport
As enumeration methods can be chained, this selection is equivalent:
select items.where(i => i.location.x = 0).where(i => i.location.y = 0) as zeroloc from LocationReport
According to above statement the engine outputs in field zeroloc
a collection of Item
objects matching the condition.
The where
enumeration method has a second version that has two lambda-parameters. The second parameter is the name of the index property which represents the current index of the element within the collection.
This sample query returns a collection that consists of the first 3 items. This sample query does not use the item
lambda parameter:
select items.where( (item, indexElement) => indexElement < 3) as firstThreeItems from LocationReport
It is not necessary to use classes for event representation. The example above applies the same to Object-array, Map or XML underlying events.
For most enumeration methods the input can be any collection of events, scalar values or objects. For some enumeration methods limitations apply that are documented below. For example, the sumOf
enumeration method requires a collection of numeric scalar values if used without parameters.
If the input to sumOf
is a collection of events or scalar values the enumeration method requires a lambda expression as parameter that yields the numeric value to use to compute the sum.
Many examples of this section operate on the collection returned by the event property items
in the LocationReport
event class.
There are many other inputs yielding collections as listed below. Most examples herein use an event property as a input simply because the example can thus be brief and does not need to refer to a subquery or named window or other concept.
For enumeration methods that return a collection, for example where
and orderBy
, the engine outputs an implementation of the Collection
interface that contains the selected value(s). The collection returned must be considered read-only. As Java does not allow resettable iterators, the Collection
interface allows more flexibility to query size and navigate among collection elements. We recommend against down-casting a collection returned by the engine to a more specific subclass of the Collection
interface.
For enumeration methods that return an element, for example firstOf
, lastOf
, minBy
and maxBy
the engine outputs the scalar value or the underlying event if operating on events. You may add an event property name after the enumeration method to return a property value.
Enumeration methods generally retain the order of elements provided by the collection.
The following restrictions apply to enumeration methods:
Enumeration methods returning a collection return a read-only implementation of the Collection
interface. You may not use any of the write-methods such as add
or remove
on a result collection.
The input of data for built-in enumeration methods is a collection of scalar values, events or other objects. Input can originate from any of the following:
A subquery.
A named window.
A property of an event that is itself a collection of events or classes, i.e. an indexed property.
Any of the event aggregation functions (window
, first
, last
, sorted
, maxby
, minby
, maxbyever
, minbyever
).
The special prevwindow
, prev
and prevtail
single-row functions.
A plug-in single-row function, a user-defined function or an enum type.
A declared expression.
Another enumeration method that returns a collection.
An array returned by the {}
array operator.
A collection or array returned by a method call on an event.
A variable. Usually variables declared as an array.
In a match-recognize pattern, a group variable.
In an EPL pattern, events collected in a repeat ([...]
) and a repeat-until (... until ...
).
Subqueries can return the rows of another stream's data window or rows from a named window. By providing a where-clause the rows returned by a subquery can be correlated to data provided by stream(s) in the from-clause. See Section 5.11, “Subqueries”.
A subquery that selects (*)
wildcard provides a collection of events as input. A subquery that selects a single value expression provides a collection of scalar values as input. Subqueries that selects multiple value expressions are not allowed as input to enumeration methods.
The following example uses a subquery to retrieve all zones for each location report item where the location falls within the rectangle of the zone. Please see a description of example events and functions above.
select assetId, (select * from Zone.std:unique(name)).where(z => inrect(z.rectangle, location)) as zones from Item
You may place the subquery in an expression declaration to reuse the subquery in multiple places of the same EPL statement.
This sample EPL declares the same query as above in an expression declaration:
expression myquery {itm => (select * from Zone.std:unique(name)).where(z => inrect(z.rectangle, itm.location)) } select assetId, myquery(item) as subq, myquery(item).where(z => z.zone = 'Z01') as assetItem from Item as item
The above query also demonstrates how an enumeration method, in the example the where
-method, can be run across the results returned by a subquery in an expression declaration.
Place a single column in the subquery select-clause to provide a collection of scalar values as input.
The next example selects all names of zones and orders the names returning an order collection of string names every 30 seconds:
select (select name from Zone.std:unique(name)).orderBy() as orderedZones from pattern[every timer:interval(30)]
The next example utilizes a subquery that counts zone events per name and finds those that have a count greater then 1:
select (select name, count(*) as cnt from Zone.win:keepall() group by name) .where(v => cnt > 1) from LocationReport]
When the subquery selects a single column that is itself an event, the result of the subquery is a collection of events of that type and can provide input to enumeration methods.
For example:
create schema SettlementEvent (symbol string);
create schema PriceEvent (symbol string, price double);
create schema OrderEvent (orderId string, pricedata PriceEvent);
select (select pricedata from OrderEvent.std:unique(orderId)) .anyOf(v => v.symbol = 'GE') as has_ge from SettlementEvent(symbol = 'GE')
Note that the engine can cache intermediate results thereby is not forced to re-evaluate the subquery for each occurrence in the select
-clause.
Named windows are globally-visible data windows. See Section 5.15, “Creating and Using Named Windows”.
You may specify the named window name as input for an enumeration method and can optionally provide a correlation where-clause. The syntax is equivalent to a sub-query against a named window but much shorter.
Synopsis:
named-window-name[(correlation-expression)].enum-method-name(...)
When selecting all events in a named window you do not need the correlation-expression. To select a subset of data in the named window, specify a correlation-expression. From the perspective of best runtime performance, a correlation expression is preferred to reduce the number of rows returned.
The following example first declares a named window to hold the last zone event per zone name:
create window ZoneWindow.std:unique(name) as Zone
Then we create a statement to insert zone events that arrive to the named window:
insert into ZoneWindow select * from Zone
Finally this statement queries the named window to retrieve all zones for each location report item where the location falls within the rectangle of the zone:
select ZoneWindow.where(z => inrect(z.rectangle, location)) as zones from Item
If you have a filter or correlation expression, append the expression to the named window name and place in parenthesis.
This slightly modified query is the example above except that it adds a filter expression such that only zones with name Z1, Z2 or Z3 are considered:
select ZoneWindow(name in ('Z1', 'Z2', 'Z3')).where(z => inrect(z.rectangle, location)) as zones from Item
You may prefix property names provided by the named window with the name to disambiguate property names.
This sample query prefixed the name
property and returns the count of matching zones:
select ZoneWindow(ZoneWindow.name in ('Z1', 'Z2', 'Z3')).countof()) as zoneCount from Item
The engine internally interprets the shortcut syntax and creates a subquery from it. Thus all indexing and query planning for subqueries against named windows apply here as well.
Indexed event properties are event properties that are a collection, array or iterable of scalar values or objects.
The LocationReport
event from the example contains a list of Item
events. Any indexed property (list, array, collection, iterable) is eligible for use as input to an enumeration method. If the indexed property contains non-scalar objects the objects are treated as events and can be used as input to enumeration methods as a collection of events.
The next sample query returns items that are less then 20 units away from the center, taking the items
event property provided by each LocationReport
event as input:
select items.where(p => distance(0, 0, p.location.x, p.location.y) < 20) as centeritems from LocationReport
The following example consists of two statements: The first statement declares an a new event type and the second statement invokes the sequenceEqual
method to compare sequences contained in two properties of the same event:
create schema MyEvent (seqone String[], seqtwo String[])
select seqone.sequenceEqual(seqtwo) from MyEvent
Event aggregation functions return an event or multiple events. They are aggregation functions and as such sensitive to the presence of group by
. See Section 9.2.2, “Event Aggregation Functions”.
You can use window
, first
or last
event aggregation functions as input to an enumeration method. Specify the *
wildcard as the parameter to the event aggregation function to provide a collection of events as input. Or specify a property name as the parameter to event aggregation function to provide a collection of scalar values as input.
You can use the sorted
, maxby
, minby
, maxbyever
or minbyever
event aggregation functions as input to an enumeration method. Specify one or more criteria expressions that provide the sort order as parameters to the event aggregation function.
In this example query the window(*)
aggregation function returns the last 10 seconds of item location reports for the same asset id as the incoming event. Among that last 10 seconds of events for the same asset id, the
enumeration method returns those item location reports where the distance to center is less then 20, for each arriving Item event.
Sample query:
select window(*).where(p => distance(0, 0, p.location.x, p.location.y) < 20) as centeritems from Item(type='P').win:time(10) group by assetId
The next sample query instead selects the asset id property of all events and returns an ordered collection:
select window(assetId).orderBy() as orderedAssetIds from Item.win:time(10) group by assetId
The following example outputs the 5 highest prices per symbol among the last 10 seconds of stock ticks:
select sorted(price desc).take(5) as highest5PricesPerSymbol from StockTick.win:time(10) group by symbol
The prev
, prevwindow
and prevtail
single-row functions allow access into a stream's data window however are not aggregation functions and and as such not sensitive to the presence of group by
. See Section 9.1.13, “The Previous-Window Function”.
When using any of the prev
single-row functions as input to a built-in enumeration method you can specify the stream name as a parameter to the function or an event property. The input to the enumeration method is a collection of events if you specify the stream name, or a collection of scalar value if you specify an event property.
In this example query the prevwindow(stream)
single-row function returns the last 10 seconds of item location reports, among which the
enumeration method filters those item location reports where the distance to center is less then 20, for each Item event that arrived in the last 10 seconds considering passenger-type Item events only (see filter type = 'P').
Sample query:
select prevwindow(items) .where(p => distance(0, 0, p.location.x, p.location.y) < 20) as centeritems from Item(type='P').win:time(10) as items
This sample query demonstrates the use of the prevwindow
function to return a collection of scalar values (collection of asset id) as input to orderby
:
select prevwindow(assetId).orderBy() as orderedAssetIds from Item.win:time(10) as items
Your single-row or user-defined function can return either an array or any collection that implements either the Collection
or Iterable
interface. For arrays, the array component type and for collections, the collection or iterable generic type should be the class providing event properties.
As an example, assume a ZoneFactory
class exists and a static method getZones()
returns a list of zones to filter items, for example:
public class ZoneFactory { public static Iterable<Zone> getZones() { List<Zone> zones = new ArrayList<Zone>(); zones.add(new Zone("Z1", new Rectangle(0, 0, 20, 20))); return zones; } }
Import the class through runtime or static configuration, or add the method above as a plug-in single-row function.
The following query returns for each Item event all zones that the item belongs to:
select ZoneFactory.getZones().where(z => inrect(z.rectangle, item.location)) as zones from Item as item
If the class and method were registered as a plug-in single-row function, you can leave the class name off, for example:
select getZones().where(z => inrect(z.rectangle, item.location)) as zones from Item as item
Your single-row or user-defined function can also return an array, collection or iterable or scalar values.
For example, the static method getZoneNames()
returns a list of zone names:
public static String[] getZoneNames() { return new String[] { "Z1", "Z2"}; }
The following query returns zone names every 30 seconds and excludes zone Z1:
select getZoneNames().where(z => z != "Z1") from pattern[every timer:interval(30)]
An enum type can also be a useful source for enumerable values.
The following sample Java declares an enum type EnumOfZones
:
public enum EnumOfZones { ZONES_OUTSIDE(new String[] {"z1", "z2"}), ZONES_INSIDE(new String[] {"z3", "z4"}) private final String[] zones; private EnumOfZones(String[] zones) { this.zones = zones; } public String[] getZones() { return zones; } }
A sample statement that utilizes the enum type is shown next:
select EnumOfZones.ZONES_OUTSIDE.getZones().anyOf(v => v = zone) from Item
A declared expression may return input data for an enumeration method.
The below query declares an expression that returns all passenger location reports among the items in the location report event in a column named passengerCollection
. The query uses the result returned by the declared expression
a second time to filter through the list returning the passenger location report where the asset id is a given value in a column named passengerP01
.
Sample query:
expression passengers { lr => lr.items.where(l => l.type='P') } select passengers(lr) as passengerCollection, passengers(lr).where(x => assetId = 'P01') as passengerP01 from LocationReport lr
The engine applies caching techniques to avoid re-evaluating the declared expression multiple times.
A variable may provide input data for an enumeration method.
This constant of array type carries a list of invalid zones:
create constant variable string[] invalid_zones = { 'Z1', 'Z2' };
Sample query:
select invalid_zones.anyOf(v => v = name) as flagged from Zone
In a match-recognize pattern, the term group variables refers to identifiers that can collect multiple events.
This example assumes an order event type and each order has an item id. This sample match-recognize pattern finds a sequence of order events that concludes with an item id matching any of the collected item ids since the last pattern match:
select * from Order match_recognize ( measures A as a_array, B as b pattern (A* B) define B as A.anyOf(v=> v.itemId = B.itemId) )
Both the define
and the measures
clause can contain expressions utilizing enumeration methods.
In an EPL pattern, the repeat and repeat-until pattern operators may collect multiple events.
The following pattern fires when two order events arrive followed by an order amendment event that has an amount larger than the largest amount of any of the preceding order events:
select * from pattern [ ([2] a=Order) -> b=OrderAmendment(amount > a.max(i => i.amount)) ]
Following the RFID asset tracking example as introduced earlier, this section introduces two use cases solved by enumeration methods.
The first use case requires us to find any luggage that is more then 20 units away from the passenger that the luggage belongs to.
The declared expression lostLuggage
solves this question.
The second question to answer is: For each of such lost luggage what single other passenger is nearest to that luggage.
The declared expression nearestOwner
which uses lostLuggage
answers this question.
Below is the complete EPL statement (one statement not multiple):
// expression to return a collection of lost luggage expression lostLuggage { lr => lr.items.where(l => l.type='L' and lr.items.some(p => p.type='P' and p.assetId=l.assetIdPassenger and LRUtil.distance(l.location.x, l.location.y, p.location.x, p.location.y) > 20)) } // expression to return all passengers expression passengers { lr => lr.items.where(l => l.type='P') } // expression to find the nearest owner expression nearestOwner { lr => lostLuggage(lr).toMap(key => key.assetId, value => passengers(lr).minBy( p => LRUtil.distance(value.location.x, value.location.y, p.location.x, p.location.y)) ) } select lostLuggage(lr) as val1, nearestOwner(lr) as val2 from LocationReport lr
The aggregate
enumeration method takes an expression providing the initialization value (seed) and an accumulator lambda expression. The return value is the final accumulator value.
Via the aggregate
method you may perform a calculation over elements. The method initializes the aggregated value by evaluating the expression provided in the first parameter. The method then calls the lambda expression of the second parameter once for each element in the input. The lambda expression receives the last aggregated value and the element from the input. The result of the expression replaces the previous aggregated value and returns the final result after completing all elements.
An expression example with scalar values:
{1, 2, 3}.aggregate(0, (result, value) => result + value) // Returns 6
The example below aggregates price of each OrderEvent in the last 10 seconds computing a total price:
// Initialization value is zero. // Aggregate by adding up the price. select window(*).aggregate(0, (result, order) => result + order.price) as totalPrice from OrderEvent.win:time(10)
In the query above, the initialization value is zero, result
is used for the last aggregated value and order
denotes the element that the expression adds the value of the price property.
This example aggregation builds a comma-separated list of all asset ids of all items:
select items.aggregate('', (result, item) => result || (case when result='' then '' else ',' end) || item.assetId) as assets from LocationReport
In above query, the empty string ''
represents the initialization value. The name result
is used for the last aggregated value and the name item
is used to denote the element.
The type value returned by the initialization expression must match to the type of value returned by the accumulator lambda expression.
If the input is null the method returns null. If the input is empty the method returns the initialization value.
The allof
enumeration method determines whether all elements satisfy the predicate condition.
The method takes a single parameter: The predicate lambda expression that must yield a Boolean result. The enumeration method applies the lambda expression to each element and if the expression returns true for all elements, the method returns true.
An expression example with scalar values:
{1, 2, 3}.allOf(v => v > 0) // Returns true as all values are > 0 {1, 2, 3}.allOf(v => v > 1) // Returns false
The EPL statement below returns true when all items are within 1000 unit distance of center:
select items.allof(i => distance(i.location.x, i.location.y, 0, 0) < 1000) as centered from LocationReport
If the input is null the method returns null. If the input is empty the method returns true.
The anyof
enumeration method determines whether any element satisfies the predicate condition.
The only parameter is the predicate lambda expression that must yield a Boolean result. The enumeration method applies the lambda expression to each element and if the expression returns true for all elements, the method returns true.
An expression example with scalar values:
{1, 2, 3}.anyOf(v => v > 0) // Returns true {1, 2, 3}.anyOf(v => v > 1) // Returns true {1, 2, 3}.anyOf(v => v > 3) // Returns false
The EPL statement below return true when any of the items are within 10 unit distance of center:
select items.anyof(i => distance(i.location.x, i.location.y, 0, 0) < 10) as centered from LocationReport
If the input is null the method returns null. If the input is empty the method returns false.
The average
enumeration method computes the average of scalar values. If passing a projection lambda expression the method computes the average obtained by invoking the projection lambda expression on each element.
The method takes a projection lambda expression yielding a numeric value as a parameter. It applies the lambda expression to each element and computes the average of the result, returning a Double value. A BigDecimal is returned for expressions returning BigInteger or BigDecimal.
An expression example with scalar values:
{1, 2, 3}.average() // Returns 2
The EPL statement as shown next computes the average distance from center among all items in the location report event:
select items.average(i => distance(i.location.x, i.location.y, 0, 0)) as avgdistance from LocationReport
If the input is null the method returns null. If the input is empty the method returns double zero or BigDecimal zero. For BigDecimal precision and rounding, please see Section 15.4.22.6, “Math Context”.
The countof
enumeration method returns the number of elements, or the number of elements that satisfy a condition.
The enumeration method has two versions: The first version takes no parameters and computes the number of elements. The second version takes a predicate lambda expression that must yield Boolean true or false, and computes the number of elements that satisfy the condition.
An expression example with scalar values:
{1, 2, 3}.countOf() // Returns 3 {1, 2, 3}.countOf(v => v < 2) // Returns 1
The next sample statement counts the number of items:
select items.countOf() as cnt from LocationReport
This example statement counts the number of items that have a distance to center that is less then 20 units:
select items.countOf(i => distance(i.location.x, i.location.y, 0, 0) < 20) as cntcenter from LocationReport
If the input is null the method returns null. If the input is empty the method returns integer zero.
The distinctOf
enumeration method returns distinct elements.
The enumeration method can take a single key-selector lambda expression as parameter and returns distinct elements according to the key yielded by the expression. For same-value keys, distinct returns the first element for that key.
An expression example with scalar values:
{2, 3, 2, 1}.distinctOf() // Returns {2, 3, 1}
This example returns items distinct by item id returning the first item for each distinct item id:
select items.distinctOf(i => itemId) as itemsNearFirst from LocationReport
The key-selector lambda expression, when provided, must return a comparable type: Any primitive or boxed or Comparable
type is permitted.
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The except
enumeration method forms a set difference of the input elements with the elements that the parameter expression yields.
The enumeration method takes a single parameter that must itself return a collection of events, objects or scalar values. The method returns the elements of the first collection that do not appear in the second collection.
An expression example with scalar values:
{1, 2, 3}.except({1}) // Returns {2, 3}
The following statement compares the items of the last location report against all items in the previous 10 location reports, and reports for each combination only those items in the current item report that are not also in the location report compared to:
select za.items.except(zb.items) as itemsCompared from LocationReport as za unidirectional, LocationReport.win:length(10) as zb
If the input is null the method returns null. For scalar values and objects equals-semantics apply.
The firstOf
enumeration method returns the first element or the first element that satisfies a condition.
The method has two versions: The first version takes no parameters and returns the first element. The second version takes a predicate lambda expression yielding true or false. It applies the lambda expression to each element and returns the first element for which the expression returns true. The return type is the element itself and not a collection. You may append a property name to return the property value for the first element.
An expression example with scalar values:
{1, 2, 3}.firstOf() // Returns 1 {1, 2, 3}.firstOf(v => v / 2 > 1) // Returns 3
In the following EPL sample the query returns the first item that has a distance to center that is less then 20 units:
select items.firstof(i => distance(i.location.x, i.location.y, 0, 0) < 20) as firstcenter from LocationReport
The next sample EPL returns the first item's asset id:
select items.firstof().assetId as firstAssetId from LocationReport
If the input is null, empty or if none of the elements match the condition the method returns null.
The groupby
enumeration method groups the elements according to a specified key-selector lambda expression. There are two version of the groupby
method.
The first version of the method takes a key-selector lambda expression and returns a Map of key with each value a list of objects, one for each distinct key that was encountered. The result is a Map<Object, Collection<Object>>
wherein object is the event underlying object.
The second version of the method takes a key-selector lambda expression and value-selector lambda expression and returns a Map of key with each value a list of values, one for each distinct key that was encountered. The result is a Map<Object, Collection<Object>>
wherein object is the result of applying the value-selector expression.
The next query filters out all luggage items using a where
method and then groups by the luggage's passenger asset id. It returns a map of
passenger asset id and the collection of luggage items for each passenger:
select items.where(type='L').groupby(i => assetIdPassenger) as luggagePerPerson from LocationReport
The query shown below generates a map of item asset id and distance to center:
select items.groupby( k => assetId, v => distance(v.location.x, v.location.y, 0, 0)) as distancePerItem from LocationReport
If the input is null the method returns null. Null values as key and value are allowed.
The intersect
enumeration method forms a set intersection of the input elements with the elements that the parameter expression yields.
The enumeration method takes a single parameter that must itself return a collection of events, objects or scalar values. The method returns the elements of the first collection that also appear in the second collection.
An expression example with scalar values:
{1, 2, 3}.intersect({2, 3}) // Returns {2, 3}
The following statement compares the items of the last location report against all items in the previous 10 location reports, and reports for each combination all items in the current item report that also occur in the other location report:
select za.items.intersect(zb.items) as itemsCompared from LocationReport as za unidirectional, LocationReport.win:length(10) as zb
If the input is null the method returns null. For scalar values and objects equals-semantics apply.
The lastOf
enumeration method returns the last element or the last element that satisfies a condition.
The method has two versions: The first version takes no parameters and returns the last element. The second version takes a predicate lambda expression yielding true or false. It applies the lambda expression to each element and returns the last element for which the expression returns true. The return type is the element itself and not a collection. You may append a property name to return the property value for the last element.
An expression example with scalar values:
{1, 2, 3}.lastOf() // Returns 3 {1, 2, 3}.lastOf(v => v < 3) // Returns 2
In the following EPL sample the query returns the last item that has a distance to center that is less then 20 units:
select items.lastof(i => distance(i.location.x, i.location.y, 0, 0) < 20) as lastcenter from LocationReport
The next sample EPL returns the last item's asset id:
select items.lastof().assetId as lastAssetId from LocationReport
If the input is null, empty or if none of the elements match the condition the method returns null.
The leastFrequent
enumeration method returns the least frequent value among a collection of values, or the least frequent value after applying a transform expression to each element.
The method has two versions: The first version takes no parameters and returns the least frequent value. The second version takes a transform lambda expression yielding the value to count occurrences for. The method applies the lambda expression to each element and returns the expression result value with the least number of occurrences. The return type is the type of value in the collection or the type of value returned by the transform lambda expression if one was provided.
An expression example with scalar values:
{1, 2, 3, 2, 1}.leastFrequent() // Returns 3
The example EPL below returns the least frequent item type, counting the distinct item types among all items for the current LocationReport event:
select items.leastFrequent(i => type) as leastFreqType from LocationReport
If the input is null or empty the method returns null. The transform expression may also yield null. A null value can be returned as the most frequent value if the most frequent value is null. If multiple values have the same number of occurrences the method returns the first value with the least number of occurrences considering the ordering of the collection.
The max
enumeration method returns the maximum value among a collection of values.
If no value-selector lambda expression is provided, the method finds the maximum.
If a value-selector lambda expression is provided, the enumeration method invokes a value-selector lambda expression on each element and returns the maximum value. The type of value returned follows the return type of the lambda expression that was provided as parameter.
An expression example with scalar values:
{1, 2, 3, 2, 1}.max() // Returns 3
The next query returns the maximum distance of any item from center:
select items.max(i => distance(i.location.x, i.location.y, 0, 0)) as maxcenter from LocationReport
The value-selector lambda expression must return a comparable type: Any primitive or boxed type or Comparable
type is permitted.
If the input is null, empty or if none of the elements when transformed return a non-null value the method returns null.
The maxBy
enumeration method returns the element that provides the maximum value returned by the value-selector lambda expression when applied to each element.
The enumeration method returns the element itself. You may append an event property name to return a property value of the element.
The next query returns the first item with the maximum distance to center:
select items.maxBy(i => distance(i.location.x, i.location.y, 0, 0)) as maxItemCenter from LocationReport
The next sample returns the type of the item with the largest asset id (string comparison) among all items:
select items.maxBy(i => assetId).type as minAssetId from LocationReport
The transform expression must return a comparable type: Any primitive or boxed type or Comparable
type is permitted.
If the input is null, empty or if none of the elements when transformed return a non-null value the method returns null.
The min
enumeration method returns the minimum value among a collection of values.
If no value-selector lambda expression is provided, the method finds the minimum.
If a value-selector lambda expression is provided, the enumeration method invokes a value-selector lambda expression on each element and returns the minimum value. The type of value returned follows the return type of the lambda expression that was provided as parameter.
An expression example with scalar values:
{1, 2, 3, 2, 1}.min() // Returns 1
The next query returns the minimum distance of any item to center:
select items.min(i => distance(i.location.x, i.location.y, 0, 0)) as mincenter from LocationReport
The transform expression must return a comparable type: Any primitive or boxed type or Comparable
type is permitted.
If the input is null, empty or if none of the elements when transformed return a non-null value the method returns null.
The minBy
enumeration method returns the element that provides the minimum value returned by the value-selector lambda expression when applied to each element.
The enumeration method returns the element itself. You may append an event property name to return a property value of the element.
The next query returns the first item with the minimum distance to center:
select items.minBy(i => distance(i.location.x, i.location.y, 0, 0)) as minItemCenter from LocationReport
The next sample returns the type of the item with the smallest asset id (string comparison) among all items:
select items.minBy(i => assetId).type as minAssetId from LocationReport
The transform expression must return a comparable type: Any primitive or boxed or Comparable
type is permitted.
If the input is null, empty or if none of the elements when transformed return a non-null value the method returns null.
The mostFrequent
enumeration method returns the most frequent value among a collection of values, or the most frequent value after applying a transform expression to each element.
The method has two versions: The first version takes no parameters and returns the most frequent value. The second version takes a transform lambda expression yielding the value to count occurrences for. The method applies the lambda expression to each element and returns the expression result value with the most number of occurrences. The return type is the type of value in the collection or the type of value returned by the transform lambda expression if one was provided.
An expression example with scalar values:
{1, 2, 3, 2, 1, 2}.mostFrequent() // Returns 2
The example EPL below returns the least frequent item type, counting the distinct item types among all items for the current LocationReport event:
select items.leastFrequent(i => type) as leastFreqType from LocationReport
If the input is null or empty the method returns null. The transform expression may also yield null. A null value can be returned as the most frequent value if the most frequent value is null. If multiple values have the same number of occurrences the method returns the first value with the most number of occurrences considering the ordering of the collection.
The orderBy
enumeration method sorts elements in ascending order according to a key. The orderByDesc
enumeration method sorts elements in descending order according to a key.
The enumeration method takes a single key-selector lambda expression as parameter and orders elements according to the key yielded by the expression. For same-value keys, it maintains the existing order.
An expression example with scalar values:
{2, 3, 2, 1}.orderBy() // Returns {1, 2, 2, 3}
This example orders all items from a location report according to their distance from center:
select items.orderBy(i => distance(i.location.x, i.location.y, 0, 0)) as itemsNearFirst, items.orderByDesc(i => distance(i.location.x, i.location.y, 0, 0)) as itemsFarFirst from LocationReport
The key-selector lambda expression must return a comparable type: Any primitive or boxed or Comparable
type is permitted.
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The reverse
enumeration method simply reverses the order of elements returning a collection.
An expression example with scalar values:
{2, 3, 2, 1}.reverse() // Returns {1, 2, 3, 2}
The following EPL reverses the items:
select items.reverse() as reversedItems from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The selectFrom
enumeration method transforms each element resulting in a collection of transformed elements.
The enumeration method applies a transformation lambda expression to each element and returns the result of each transformation as a collection. Use the new
operator to yield multiple values for each element, see Section 8.13, “The 'new' Keyword”.
The next EPL query returns a collection of asset ids:
select items.selectFrom(i => assetId) as itemAssetIds from LocationReport
This sample EPL query evaluates each item and returns the asset id as well as the distance from center for each item:
select items.selectFrom(i => new { assetId, distanceCenter = distance(i.location.x, i.location.y, 0, 0) } ) as itemInfo from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The sequenceEqual
enumeration method determines whether two collections are equal by comparing each element.
The method enumerates the two source collections in parallel and compares corresponding elements by using the equals
method to compare. The method takes a single parameter expression that must return a collection containing elements of the same type as the input. The method returns true if the two source sequences are of equal length and their corresponding elements are equal.
An expression example with scalar values:
{1, 2, 3}.sequenceEqual({1}) // Returns false {1, 2, 3}.sequenceEqual({1, 2, 3}) // Returns true
The following example compares the asset id of all items to the asset ids returned by a method ItemUtil.redListed()
which is assumed to return a list of asset id of string type:
select items.selectFrom(i => assetId).sequenceEquals(ItemUtil.redListed()) from LocationReport
If the input is null the method returns null.
The sumOf
enumeration method computes the sum. If a projection lambda expression is provided, the method invokes the projection lambda expression on each element and computes the sum on each returned value.
The projection lambda expression should yield a numeric value, BigDecimal or BigInteger value. Depending on the type returned by the projection lambda expression the method returns either Integer, Long, Double, BigDecimal or BigInteger.
An expression example with scalar values:
{1, 2, 3}.sumOf() // Returns 6
The following example computes the sum of the distance of each item to center:
select items.sum(i => distance(i.location.x, i.location.y, 0, 0) as totalAllDistances from LocationReport
If the input is null or empty the method returns null.
The take
enumeration method returns a specified number of contiguous elements from the start.
The enumeration method takes a single size (non-lambda) expression that returns an Integer value.
An expression example with scalar values:
{1, 2, 3}.take(2) // Returns {1, 2}
The following example returns the first 5 items:
select items.take(5) as first5Items from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The takeLast
enumeration method returns a specified number of contiguous elements from the end.
The enumeration method takes a single size (non-lambda) expression that returns an Integer value.
An expression example with scalar values:
{1, 2, 3}.takeLast(2) // Returns {2, 3}
The following example returns the last 5 items:
select items.takeLast(5) as last5Items from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The takeWhile
enumeration method returns elements from the start as long as a specified condition is true.
The enumeration method has two versions. The first version takes a predicate lambda expression and the second version takes a predicate lambda expression and index for use within the predicate expression. Both versions return elements from the start as long as the specified condition is true.
An expression example with scalar values:
{1, 2, 3}.takeWhile(v => v < 3) // Returns {1, 2} {1, 2, 3}.takeWhile((v,ind) => ind > 2) // Returns {1, 2} {1, 2, -1, 4, 5, 6}.takeWhile((v,ind) => ind < 5 and v > 0) // Returns {1, 2} (Take while index<5 amd value>0)
This example selects all items from a location report in the order provided until the first item that has a distance to center greater then 20 units:
select items.takeWhile(i => distance(i.location.x, i.location.y, 0, 0) < 20) from LocationReport
The second version of the where
represents the index of the input element starting at zero for the first element.
The next example is similar to the query above but also limits the result to the first 10 items:
select items.takeWhile((i, ind) => distance(i.location.x, i.location.y, 0, 0) < 20) and ind < 10) from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The takeWhileLast
enumeration method returns elements from the end as long as a specified condition is true.
The enumeration method has two versions. The first version takes a predicate lambda expression and the second version takes a predicate lambda expression and index for use within the predicate expression. Both versions return elements from the end as long as the specified condition is true.
An expression example with scalar values:
{1, 2, 3}.takeWhileLast(v => v < 3) // Returns {} (empty collection) {1, 2, 3}.takeWhileLast(v => v > 1) // Returns {2, 3} {1, 2, 3}.takeWhileLast((v,ind) => ind > 2) // Returns {2, 3} {1, 2, -1, 4, 5, 6}.takeWhileLast((v,ind) => ind < 5 and v > 0) // Returns {4, 5, 6} (Take while index<5 amd value>0)
This example selects all items from a location report, starting from the last element and proceeding backwards, until the first item that has a distance to center greater then 20 units:
select items.takeWhile(i => distance(i.location.x, i.location.y, 0, 0) < 20) from LocationReport
The second version provides the index of the input element starting at zero for the last element (reverse index).
The next example is similar to the query above but also limits the result to the last 10 items:
select items.takeWhile((i, ind) => distance(i.location.x, i.location.y, 0, 0) < 20) and ind < 10) from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.
The toMap
enumeration method returns a Map according to specified key-selector lambda expression and value-selector lambda expression.
The enumeration method takes a key-selector expression and a value-selector expression. For each element the method applies the key-selector expression to determine the map key and the value-selector expression to determine the map value. If the key already exists in the map the value is overwritten.
The next example EPL outputs a map of item asset id and distance to center for each item:
select items.toMap(k => k.assetId, v => distance(v.location.x, v.location.y, 0, 0)) as assetDistance from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty map.
The union
enumeration method forms a union of the input elements with the elements that the parameter expression yields.
The enumeration method takes a single parameter that must itself return a collection of events (input), objects or scalar values. It appends the collection to the input elements and returns the appended collection of elements.
An expression example with scalar values:
{1, 2, 3}.union({4, 5}) // Returns {1, 2, 3, 4, 5}
This example selects a union of all items that have an asset id of L001 or that are of type passenger:
select items.where(i => i.assetId = 'L001') .union(items.where(i => i.type = 'P')) as itemsUnion from LocationReport
If the input is null the method returns null.
The where
enumeration method filters elements based on a predicate.
The enumeration method has two versions. The first version takes a predicate lambda expression and the second version takes a predicate lambda expression and index for use within the predicate expression. Both version returns all elements for which the predicate expression is true.
An expression example with scalar values:
{1, 2, 3}.where(v => v != 2) // Returns {1, 3}
This example selects all items from a location report that are passenger-type:
select items.where(p => p.type = 'P') from LocationReport
The second version of the where
represents the index of the input element starting at zero for the first element.
The example below selects all items from a location report that are passenger-type but ignores the first 3 elements:
select items.where((p, ind) => p.type = 'P' and ind > 2) from LocationReport
If the input is null the method returns null. If the input is empty the method returns an empty collection.