Support and Documentation

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.

  • Use contains on short text fields such as a name or title.

  • Use matches for large bodies of text.

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.

Example 50. Constructing a compound predicate with methods
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

1

Initializes username and project code.

2

Retrieves corresponding User and Project records.

3

Instantiates required Date record.

4

Instantiates a Query object for retrieving activities.

5

Builds a compound predicate from the previously retrieved objects using the and and not methods.

6

Executes query.



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

1

Search variables as defined in the snippet Constructing a compound predicate with methods.

2

Initializes comparison and compound operators. See PredicateParser for the complete list of compound operators.

3

Creates a ComparisonPredicate object that filters activity objects by the specified user.

4

Creates a CompoundPredicate object that filters activity objects by the specified date.

5

Creates a CompoundPredicate object that filters activity objects by the specified project.

6

Creates a CompoundPredicate object from a list of the previous CompoundPredicate objects and excludes instances of activity type logon.

7

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);
}