Filters for Data Reading
Filters are widely used throughout the Groovy API. You will find them in all kinds of search calls where they are used to filter data.
You might also want to read the section Searching API to find out how filters are actually used.
In this section:
Creating Filters
Filter objects can be instantiated and manipulated with the Filter class static methods:
def myFilter = Filter.equal("name", "Bob"); // creates a filter with the OP_EQUAL operator
The following filtering operators are available:
Operator | Notes | Example |
---|---|---|
EQUAL | Filter.equal("name", "Bob") | |
NOT_EQUAL | Filter.notEqual("age", 5) | |
GREATER_THAN | Filter.greaterThan("age", 5) | |
GREATER_OR_EQUAL | Filter.greaterOrEqual("name", "M") | |
LESS_THAN | Filter.lessThan("name", "N") | |
LESS_OR_EQUAL | Filter.lessOrEqual("age", 65) | |
IN | Equals to one of the items in the list of values. The value can be a collection or an array. | Filter.in("eyeColor", EyeColor.BLUE, EyeColor.HAZEL) |
NOT_IN | Filter.notIn("hairColor", HairColor.BROWN, HairColor.BLACK) | |
LIKE | Takes an SQL like expression. | Filter.like("name", "Wil%") |
ILIKE | LIKE + ignore case | Filter.ilike("name", "wil%") |
NULL | SQL IS NULL | Filter.isNull("primaryDoctor") |
NOT_NULL | Filter.isNotNull("phone") | |
EMPTY | NULL or empty string or empty collection/association | Filter.isEmpty("children") |
NOT_EMPTY | Filter.isNotEmpty("primaryDoctor.firstName") | |
SOME | Applies to collection/association properties. Takes another Filter as a value, and matches when at least one of the values in the collection matches the filter. | Filter.some("children", Filter.equal("name", "Joey")) |
ALL | The same as SOME, except that all values must match the filter. | Filter.all("children", Filter.greaterOrEqual("age", 18)) |
NONE | The same as SOME, except that none of the values may match the filter. | Filter.none("pets", Filter.and(Filter.equal("species", "cat"), Filter.lessThan("age", .75)) //has no cats under 9 months old |
AND | Takes no property. Takes an array or collection of Filters as a value. Matches when all the filters in the value match. | Filter.and(Filter.greaterOrEqual("age", 40), Filter.lessThan("age", 65)) |
OR | The same as AND, except that it matches when any of the filters match. | Filter.or(Filter.like("firstName", "Wil%"), Filter.like("lastName", "Wil%")) |
NOT | Takes no property. Takes a single Filter as a value. Matches when the filter in the value does not match. | Filter.not(Filter.ilike("name", "W%")) //name does not start with 'w' |
When building complex filters, it is recommended to format the code in a structure like this:
def myFilter =
Filter.or(
Filter.equal("name", "Jack"),
Filter.and(
Filter.equal("name", "Jill"),
Filter.like("location", "%Chicago%"),
Filter.greaterThan("age", 5)
)
)
Using Filters
To get the idea how you can use a filter, see the following example:
def prices = api.productExtension("ListPrices", Filter.equal("sku", api.product("sku")), Filter.lessOrEqual("attribute1", 200))
In this example, the query returns all rows from Product Extension called "ListPrices" which are assigned to the current product and whose price is less or equal to 200.
For more examples see Data Reading Functions where the filters are used extensively.
Tidying up Filters
Filters are very often used for multiple fields and writing many filters in one row makes the code not well readable and produces long lines like this:
Unreadable code
A better approach is to group them in a list and save into a variable:
Readable code
Then use the Spread operator *
to expand this list to function parameters:
The code style above is more readable and reusable. It can be easily copied and quickly adjusted.
If you need to parametrize the filters, you can create a function that returns such a list instead:
Parametrized filter
And here is the sample call:
Known Issues
Filtering on NULL Values with Filter.notEqual() Returns No Rows
When filtering on NULL values together with the Filter.notEqual() filter, you must be aware of the fact that DB treats NULL values as unknown, which could result in an unexpected behavior.
See the following example. Let's say we want to retrieve all values except when Attribute1 equals 'A'.
SKU | Label | Attribute1 |
---|---|---|
001 | Product 1 | NULL |
002 | Product 2 | NULL |
003 | Product 3 | A |
The common sense tells you to use Filter.notEqual("attribute1", "A")
but this returns no rows. That is because you need to treat the NULL values using Filter.isNull()
or Filter.isNotNull()
.
The following code works:
Further Reading
As the whole filtering API is largely based on an opensource project (but not 100% identical anymore), you may also have a look at their documentation. Chances are that the options described there will also work in the Groovy code:
Found an issue in documentation? Write to us.