Predicate Language
The predicate language is designed for convenient use on both the frontend and backend sides — for modification, analysis, and other operations.
From an abstract definition standpoint, a predicate is a function that takes an element of some set and returns True or False.
The ecos-records library provides an implementation of this concept.
A predicate has two aggregate representations — JSON or Java classes. To convert between these two states, the PredicateService and the writeJson/readJson methods are available. The Java representation is simply a model.
Model processing is a separate concern handled by data sources or query transformers (for example, for Alfresco queries, predicates are transformed into an fts-alfresco query in the PredicateToFtsAlfrescoConverter class).
Java Representation
Predicate — base marker interface with no methods
AttributePredicate — predicate associated with a specific attribute
EmptyPredicate — predicate “Attribute value is empty”
ValuePredicate — predicate “Attribute value equals / contains / is one of / greater than / less than / matches / greater than or equal / less than or equal”. The comparison type is defined by the type field. The comparison value is in the value field
NotPredicate — predicate “NOT some_other_predicate”
ComposedPredicate — predicate that combines other predicates
AndPredicate — AND predicate
OrPredicate — OR predicate
VoidPredicate — empty predicate produced when t (type) is not set. Usually means that no checks are needed during filtering/search (all records are returned).
JSON Representation
Example:
{
"t": "and",
"val": [
{
"t": "or",
"val": [
{
"att": "country",
"t": "contains",
"val": "milan"
},
{
"att": "state",
"t": "contains",
"val": "milan"
},
{
"att": "name",
"t": "contains",
"val": "milan"
}
]
}
]
}
The “t” field holds the predicate type, “att” holds the attribute name (if the predicate type requires it), and “val” holds the value (again, only meaningful for some predicates).
To convert Java predicates to JSON and back:
String predicateStr = Json.getMapper().toString(predicate);
Predicate predicate = Json.getMapper().read(predicateStr, Predicate.class);
To read predicates from a RecordsQuery request:
Predicate predicate = recordsQuery.getQuery(Predicate.class);
Predicate Types
Predicate |
Description |
FTS |
|---|---|---|
starts |
The string starts with val.
Example:
|
|
ends |
The string ends with val.
Example:
|
|
or |
Combines the array of predicates in val using OR.
Example:
|
|
and |
Combines the array of predicates in val using AND.
Example:
|
|
empty |
The field specified in att is empty.
Example:
|
|
not |
Negation of the predicate in val.
Example:
This predicate can be automatically prepended to others by adding the “not-” prefix.
Example:
|
|
eq |
The value of the att field is exactly equal to val.
Example:
|
|
gt |
The value of the att field is greater than val
|
|
ge |
The value of the att field is greater than or equal to val
|
|
lt |
The value of the att field is less than val
|
|
le |
The value of the att field is less than or equal to val
|
|
like |
The att value matches the val pattern.
In the pattern, % is used as a wildcard for any number of characters (as in a database SELECT query)
|
|
in |
The att value matches the val pattern.
|
|
contains |
The att value contains the val substring (also works for associations)
|
For example:
Additional Predicate Features
Feature |
Description |
|---|---|
Ranges and Durations |
For attributes of type date and datetime, the ability to compute durations and ranges has been added
When a range is specified with the first boundary, it is calculated from the current date and time
When a range is specified with the second boundary, it is calculated from the first boundary
The search is inclusive of boundaries, i.e. [DurationOrDateTime1, DurationOrDateTime2]
Two constants are available: $NOW — current date and time, $TODAY — current date
Examples:
Find documents created within the last 10 days:
Find documents where the range is from $NOW minus two years, to ($NOW minus two years) plus one year
Find documents created within the last 2 years, up to the current date and time
Find documents created within the last 2 years, up to today
from 2020-01-01 to 2020-02-01
from 2020-01-01 to 2020-01-01 plus 1 month
from minus 10 days to 2020-01-01
from today
|
Predicate Debugging
To debug predicates, you can use the following script in the browser console:
await Records.queryOne({
sourceId: 'uiserv/predicate',
query: {
record: 'emodel/sed-agreement@8a2964d4-e83b-4337-b033-05e7e4a232fc',
predicate: {
"t": "and",
"val": [
{
"t": "not",
"val": {
"t": "eq",
"att": "_status?str",
"val": "Canceled"
}
}
]
}
}
}, 'result?bool')
JSON <-> YAML conversion can be done unambiguously in any online service by searching for “yaml to json converter”.
It is also useful for debugging to load attribute values and verify what is being compared with what:
await Records.get(
'emodel/sed-agreement@8a2964d4-e83b-4337-b033-05e7e4a232fc'
).load([
'_status?str',
"_status?id",
"_status?disp",
"_roles.isCurrentUserMemberOf.author?bool",
"_roles.isCurrentUserMemberOf.admin?bool"
]);
{
"_status?str": "Canceled",
"_status?id": "emodel/sed-agreement@Canceled",
"_status?disp": "Отменено",
"_roles.isCurrentUserMemberOf.author?bool": false,
"_roles.isCurrentUserMemberOf.admin?bool": true
}
Showing a button under specific conditions described by a predicate
_status is a localized text field, therefore _status?str is used
t: not
val:
t: in
att: _status?str
val:
- draft
- Canceled
- Rejected