Predicates
The includes several methods to filter search results based on specified conditions, such as where, and, or, and not. Conditions are expressed with compound, comparison, and other predicates, as described below:
Basic comparisons
Basic Comparisons | |
=, eq | The left-hand expression is equal to the right-hand expression. |
>=, => | The left-hand expression is greater than or equal to the right-hand expression. |
<=, =< | The left-hand expression is less than or equal to the right-hand expression. |
> | The left-hand expression is greater than the right-hand expression. |
< | The left-hand expression is less than the right-hand expression. |
!=, <> | The left-hand expression is not equal to the right-hand expression. |
Boolean predicates | |
true | A predicate that always evaluates to TRUE. |
false |
A predicate that always evaluates to FALSE. |
Basic compound predicates | |
AND, && | Logical AND. |
OR, || | Logical OR. |
NOT | Logical NOT. |
String comparisons | |
startsWith | The value of the field specified in the left-hand expression begins with the right-hand expression. |
matches | The left-hand expression matches right-hand expression using a full-text search. |
contains | The left-hand expression partially or completely matches right-hand expression.
|
Other predicates | |
missing | The left-hand expression is missing. |
Predicates are used for testing field values. Fields evaluated with predicate operations must be annotated with @Recordable.Indexed.
The where
method is the most common Query method for testing field values. For example, the following query uses a comparison operator =
to return all Activity
instances with an activityType
field value equal to checkin
.
Query<Activity> query = Query.from(Activity.class);
query.where("activityType = 'checkin'");
List<Activity> activities = query.selectAll();
You can include logical operations in the where
method.
Query<Activity> query = Query.from(Activity.class);
query.where("activityType = 'checkin' or activityType = 'cancel'");
List<Activity> activities = query.selectAll();
Logical operations can also be expressed with Query compound clauses.
Query<Activity> query = Query.from(Activity.class);
query.where("activityType = 'checkin'");
query.or("activityType = 'cancel'");
List<Activity> activities = query.selectAll();
In the above examples, the Query object returned from the from
method is used for all subsequent methods called on the object. As an alternative to creating a separate statement for each Query method, you can chain the methods in one statement.
List<Activity> activities = Query.from(Activity.class)
.where("activityType = 'checkin'")
.or("activityType = 'cancel'")
.selectAll();
Predicates can be expressed as strings or objects. In the previous examples, strings are used in various Query methods. However, there are versions of these methods that take a Predicate object to express logical and comparison operations.
The following examples contrast two versions of Query methods that take predicate arguments. The first example retrieves an activity log for a given date, project, and user except for the activity logon.
Constructing a compound predicate with methods
String name = "aHoward";
String projCode = "evans-26-b825";
User user = Query.from(User.class).where("userName = ?", name).first();
Project project = Query.from(Project.class).where("code = ?", projCode).first();
Date date = new SimpleDateFormat("MM/dd/yyyy").parse("03/27/2017");
Query<Activity> query = Query.from(Activity.class);
query.where("activityUser = ?", user);
query.and("activityDate = ?", date);
query.and("project = ?", project);
query.not("activityType = ?", "logon");
return query.selectAll();
-
Initializes username and project code.
-
Retrieves corresponding User and Project records.
-
Instantiates required Date record.
-
Instantiates a Query object for retrieving activities.
-
Builds a compound predicate from the previously retrieved objects using the and and not methods.
-
Executes query.
The following example executes the same query using the Predicate class.
String name = "aHoward";
String projCode = "evans-26-b825";
Query<Activity> query = Query.from(Activity.class);
String opEqualsAny = PredicateParser.EQUALS_ANY_OPERATOR;
String opAnd = PredicateParser.AND_OPERATOR;
String opNotEqualsAll = PredicateParser.NOT_EQUALS_ALL_OPERATOR;
Predicate predicate = new ComparisonPredicate(opEqualsAny, true, "activityUser", Arrays.asList(user));
predicate = new CompoundPredicate(opAnd,
Arrays.asList(predicate,
new ComparisonPredicate(comparisonEqualsAny, true, "activityDate", Arrays.asList(date))));
predicate = new CompoundPredicate(opAnd,
Arrays.asList(predicate,
new ComparisonPredicate(comparisonOp, true, "project", Arrays.asList(project))));
predicate = new CompoundPredicate(opNotEqualsAll,
Arrays.asList(predicate,
new ComparisonPredicate(comparisonOp, true, "activityType", Arrays.asList("logon"))));
return query.where(predicate).selectAll();
-
Search variables as defined in the snippet Constructing a compound predicate with methods above.
-
Initializes comparison and compound operators. See for the complete list of compound operators.
-
Creates a
ComparisonPredicate
object that filters activity objects by the specified user. -
Creates a
CompoundPredicate
object that filters activity objects by the specified date. -
Creates a
CompoundPredicate
object that filters activity objects by the specified project. -
Creates a
CompoundPredicate
object from a list of the previousCompoundPredicate
objects and excludes instances of activity type logon. -
Executes query.
The PredicateParser
class includes EQUALS_ANY_OPERATOR
. This operator uses OR logic, where foo = [ a, b, c ]
translates to foo = a OR foo = b OR foo = c
.
Consider an Article
type with a categories list field, used to enter subject categories. You could use the PredicateParser.EQUALS_ANY_OPERATOR
to find articles in the categories environment, nature, or politics.
Predicate predicate = new ComparisonPredicate(PredicateParser.EQUALS_ANY_OPERATOR, true, "category", Arrays.asList("environment","nature","politics"));
However, to find articles with all of the category values of “environment” and “nature” and “politics”, you would need to apply “equalsall” logic. This operator uses AND logic, where foo = [ a, b, c ]
translates to foo = a AND foo = b AND foo = c
.
Because PredicateParser
does not include an “equalsall” operator, you need to build a query that tests for the inclusion of each value in a list field. For example, the following for loop would build a query to find articles categorized with “environment” and “nature” and “politics."
ArrayList<String> subjects = new ArrayList<String>();
subjects.add("environment");
subjects.add("nature");
subjects.add("politics");
for (String subject : subjects) {
query.and("categories = ?", subject);
}
The class includes NOT_EQUALS_ALL_OPERATOR. This operator uses AND logic, where foo != [ a, b, c ] translates to foo != a AND foo != b AND foo != c.
Consider an Article type with a categories list field, used to enter subject categories. You could use the PredicateParser.NOT_EQUALS_ALL_OPERATOR to find articles not included in the categories environment, nature, and politics.
Predicate predicate = new ComparisonPredicate(PredicateParser.NOT_EQUALS_ALL_OPERATOR, true, "category", Arrays.asList("environment","nature","politics"));
However, to find articles with none of the category values of “environment” or “nature” or “politics”, you would need to apply “notequalsany” logic. This operator uses OR logic, where foo != [ a, b, c ] translates to foo != a OR foo != b OR foo != c.
Because PredicateParser does not include a “notequalsany” operator, you need to build a query that tests for the exclusion of each value in a list field. For example, the following for loop would build a query to find articles that are not categorized with “environment” or “nature” or “politics.”
ArrayList<String> subjects = new ArrayList<String>();
subjects.add("environment");
subjects.add("nature");
subjects.add("politics");
for (String subject : subjects) {
query.and("categories != ?", subject);
}