Predicates
The Query API 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 | |
=, 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();
Advanced predicates
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
.
String name = "aHoward"; 1 String projCode = "evans-26-b825"; User user = Query.from(User.class).where("userName = ?", name).first(); 2 Project project = Query.from(Project.class).where("code = ?", projCode).first(); Date date = new SimpleDateFormat("MM/dd/yyyy").parse("03/27/2017"); 3 Query<Activity> query = Query.from(Activity.class); 4 query.where("activityUser = ?", user); 5 query.and("activityDate = ?", date); query.and("project = ?", project); query.not("activityType = ?", "logon"); return query.selectAll(); 6
The following example executes the same query using the Predicate
class.
String name = "aHoward"; 1 String projCode = "evans-26-b825"; Query<Activity> query = Query.from(Activity.class); String opEqualsAny = PredicateParser.EQUALS_ANY_OPERATOR; 2 String opAnd = PredicateParser.AND_OPERATOR; String opNotEqualsAll = PredicateParser.NOT_EQUALS_ALL_OPERATOR; Predicate predicate = new ComparisonPredicate(opEqualsAny, true, "activityUser", Arrays.asList(user)); 3 predicate = new CompoundPredicate(opAnd, 4 Arrays.asList(predicate, new ComparisonPredicate(comparisonEqualsAny, true, "activityDate", Arrays.asList(date)))); predicate = new CompoundPredicate(opAnd, 5 Arrays.asList(predicate, new ComparisonPredicate(comparisonOp, true, "project", Arrays.asList(project)))); predicate = new CompoundPredicate(opNotEqualsAll, 6 Arrays.asList(predicate, new ComparisonPredicate(comparisonOp, true, "activityType", Arrays.asList("logon")))); return query.where(predicate).selectAll(); 7
Search variables as defined in the snippet Constructing a compound predicate with methods. | |
Initializes comparison and compound operators. See PredicateParser for the complete list of compound operators. | |
Creates a | |
Creates a | |
Creates a | |
Creates a | |
Executes query. |
Equals all condition
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); }
Not equals any condition
The PredicateParser 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); }