Free cookie consent management tool by TermsFeed

a!queryLogicalExpression() Function

On This Page

Creates a LogicalExpression object that determines the filtration to apply in Query object.

Related function:

  • a!queryFilter(): Creates individual filter conditions to use within a!queryLogicalExpression().

Parameters

a!queryLogicalExpression( operator, logicalExpressions, filters, ignoreFiltersWithEmptyValues )

Keyword Type Description

operator

Text

Determines the operation to apply to the set filters. Valid values: "AND", "OR", and "AND_ALL". The "AND_ALL" operator is only valid when filtering on multiple fields from a one-to-many relationship.

logicalExpressions

List of LogicalExpression

A list of LogicalExpression objects to apply using the operator parameter, created with a!queryLogicalExpression().

filters

List of QueryFilter

A list of QueryFilters to apply using the operator parameter, created with a!queryFilter().

ignoreFiltersWithEmptyValues

Boolean

Specifies whether to ignore filters within a!queryLogicalExpression() if the filter's value parameter is empty. If you are using nested logical expressions, this parameter must have the same value for each logical expression. For example, if the value is set to true for the parent logical expression, it should be set to true for all children logical expressions. Default: false

Returns

LogicalExpression

Using the function

The following sections cover important details about the a!queryLogicalExpression() function.

When to use a!queryLogicalExpression

Use a!queryLogicalExpression() when you need to control how multiple filter conditions are combined in a query.

Without a!queryLogicalExpression(), multiple filter conditions are evaluated with an "AND" operator by default. For example, if you filter on both title and start date, the query only returns records that match both conditions. To return records that match either condition, use a!queryLogicalExpression() with the "OR" operator.

See Filter on two different conditions for a full example.

Where to use a!queryLogicalExpression

You can use a!queryLogicalExpression() to define how multiple filters are combined in the following locations:

Using the logicalExpression parameter

Use the logicalExpression parameter when you need to combine filter groups that use different operators, such as requiring one condition AND (another condition OR a third).

See an example filtering on nested conditions.

There are three valid values for the operator parameter:

  • "OR"
  • "AND"
  • "AND_ALL"

The "AND_ALL" operator is only available when you filter by multiple fields from the same one-to-many relationship.

The following table summarizes when to use the "AND_ALL" or "AND" operator for one-to-many relationship filters:

Operator Behavior Use when Example
"AND_ALL" (stricter) A single related record must meet all filter conditions. Returns fewer results. You need one related record to satisfy every condition on its own. Return customers with a case that is both active AND created this week.
"AND" (looser) Conditions can be spread across different related records—at least one related record meets each condition. Returns more results. You need to match conditions that may be met by separate related records. Return customers with at least one open case AND at least one in-progress case (two different cases).

Note:  Filters in a query always filter the base record type. To filter which related records are returned, use a!relatedRecordData() in your query.

How AND_ALL works

The "AND_ALL" operator filters the base record type by multiple related record fields from the same one-to-many relationship (that is, the "many" side of the relationship). It returns all records from the base record type (the "one" side) where a single related record meets all filter conditions.

For example, the following expression uses the "AND_ALL" operator to return customers that have a related case meeting both filter conditions (an active support case created within the last week):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a!queryRecordType(
  recordType: recordType!Customer,
  fields: {
    recordType!Customer.fields.displayName,
    recordType!Customer.relationships.cases.fields.isActive,
    recordType!Customer.relationships.cases.fields.createdOn,
  },
  filters: a!queryLogicalExpression(
    operator: "AND_ALL",
    filters: {
      a!queryFilter(
        field: recordType!Customer.relationships.cases.fields.isActive,
        operator: "=",
        value: true
      ),
      a!queryFilter(
        field: recordType!Customer.relationships.cases.fields.createdOn,
        operator: "<=",
        value: today()-7
      )
    }
  ),
  pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 500)
).data

With AND_ALL, only customers whose single case meets both conditions are returned:

1
2
3
4
5
6
7
8
9
10
Customer
  displayName: "Acme Corp"
  cases:
    isActive: true
    createdOn: 2026-05-28
Customer
  displayName: "Globex Industries"
  cases:
    isActive: true
    createdOn: 2026-05-26

With AND, customers are also returned when different cases each meet one condition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Customer
  displayName: "Acme Corp"
  cases:
    isActive: true
    createdOn: 2026-05-28
Customer
  displayName: "Globex Industries"
  cases:
    isActive: true
    createdOn: 2026-05-26
Customer
  displayName: "Pinnacle Solutions"
  cases:
    isActive: true
    createdOn: 2026-03-15
    isActive: false
    createdOn: 2026-05-27

Notice that "Pinnacle Solutions" appears in the "AND" results but not in the "AND_ALL" results. This customer has two separate cases: one that is active (but not created this week) and another created this week (but not active). With "AND", the conditions can be satisfied by different related records. With "AND_ALL", a single related record must meet all conditions on its own.

Note:  If your "AND_ALL" expression also includes filters that do not reference a one-to-many field, the "AND_ALL" operator evaluates those filters as a normal "AND" condition.

Filter by fields from multiple one-to-many relationships

To filter by fields from multiple one-to-many relationships, create a nested a!queryLogicalExpression() so you can evaluate both sets of filters with "AND_ALL".

For example, you want to return all customers that have an active case created in the last week, and those cases must also have at least one comment from a specific support engineer from the last day. The Customer record type has a one-to-many relationship with the Case record type, and the Case record type has a one-to-many relationship with the Comment record type.

First, filter on the one-to-many relationship between customers and cases using "AND_ALL" to return all customers with active cases created this week. Then, create a nested logical expression using "AND_ALL" to filter those cases by comments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
a!queryRecordType(
  recordType: recordType!Customer,
  fields: {
    recordType!Customer.fields.name,
    recordType!Customer.relationships.cases.fields.title,
    recordType!Customer.relationships.cases.relationships.comments.fields.createdBy
  },
  filters: a!queryLogicalExpression(
    operator: "AND_ALL",
    filters: {
      a!queryFilter(
        field: recordType!Customer.relationships.cases.fields.isActive,
        operator: "=",
        value: true
      ),
      a!queryFilter(
        field: recordType!Customer.relationships.cases.fields.createdOn,
        operator: "<=",
        value: today()-7
      )
    },
    logicalExpressions: a!queryLogicalExpression(
      operator: "AND_ALL",
      filters: {
        a!queryFilter(
          field: recordType!Customer.relationships.cases.relationships.comments.fields.createdOn,
          operator: "<=",
          value: today()
        ),
        a!queryFilter(
          field: recordType!Customer.relationships.cases.relationships.comments.fields.createdBy,
          operator: "=",
          value: "karen.anderson"
        )
      }
    )
  ),
  pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 100)
)

Both sets of filters must start from the same shared relationship: recordType!Customer.relationships.cases. You cannot create a nested filter that starts from a different one-to-many relationship.

For example, changing the nested a!queryLogicalExpression() from recordType!Customer.relationships.cases.relationships.comments to recordType!Customer.relationships.orders would cause an error.

Using the ignoreFiltersWithEmptyValues parameter

When ignoreFiltersWithEmptyValues is false (the default), filters with empty values are still evaluated, which can cause the query to return no results. Set this parameter to true to skip any filter whose value is empty. This is useful when your filters are driven by user input and some fields may be left blank.

For example, if you have a search form with optional filters for department, title, and start date, setting ignoreFiltersWithEmptyValues to true ensures the query still returns results even when a user only fills in one of the three fields.

Examples

The following examples demonstrate a!queryLogicalExpression().

The examples reference record types from another environment and will error if you try to use them in yours. Use them as a reference only.

For more examples, see Recipes for Querying Records and Recipes for Querying Entities.

Filter on two different conditions

To return employees who have a title of "Senior" or started before a certain date, use a!queryLogicalExpression() with the "OR" operator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
a!queryRecordType(
  recordType: recordType!AT Employee,
  fields: {
    recordType!AT Employee.fields.firstName,
    recordType!AT Employee.fields.lastName,
    recordType!AT Employee.fields.title,
    recordType!AT Employee.fields.startDate,
    recordType!AT Employee.relationships.department.fields.value

  },
  /* Apply queryLogicalExpression to combine */
  /* both filters with an "OR" operator  */
  filters: a!queryLogicalExpression(
    operator: "OR",
    filters: {
      a!queryFilter(
        field: recordType!AT Employee.fields.title,
        operator: "includes",
        value: "Senior"
      ),
      a!queryFilter(
        field: recordType!AT Employee.fields.startDate,
        operator: ">=",
        value: date(2016, 01, 01)
      )
    }
  ),
  pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 10)
).data

The expression above would return employees like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
AT Employee
  id: 3
  firstName: "Marcus"
  lastName: "O'Brien"
  title: "Senior Software Engineer"
  startDate: "3/14/2021"
  department: 
    id: 1,
    value: "Engineering"
AT Employee
  id: 3
  firstName: "Elena"
  lastName: "Vasquez"
  title: "Data Analyst"
  startDate: "12/8/2019"
  department: 
    id: 2,
    value: "Finance"

Filter on nested conditions

To return employees from the Engineering department who have a title of "Senior" or started before a certain date, nest two a!queryLogicalExpression() functions: one for the "AND" condition and one for the "OR" condition.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
a!queryRecordType(
  recordType: recordType!AT Employee,
  fields: {
    recordType!AT Employee.fields.firstName,
    recordType!AT Employee.fields.lastName,
    recordType!AT Employee.fields.title,
    recordType!AT Employee.fields.startDate,
    recordType!AT Employee.relationships.department.fields.value
  },
  filters: a!queryLogicalExpression(
  /* First operator combines all three filter conditions with an AND */
    operator: "AND",
  /* Employees must be in the Engineering department */
    filters: a!queryFilter(
      field: recordType!AT Employee.relationships.department.fields.value,
      operator: "=",
      value: "Engineering"
    ),
  /* Engineering department employees must have */
  /* either a senior title OR started before a certain date */
    logicalExpressions: a!queryLogicalExpression(
      operator: "OR",
      filters: {
        a!queryFilter(
          field: recordType!AT Employee.fields.title,
          operator: "includes",
          value: "Senior"
        ),
        a!queryFilter(
          field: recordType!AT Employee.fields.startDate,
          operator: ">=",
          value: date(2016, 01, 01)
        )
      }
    )
  ),
  pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 10)
).data

The expression above would return employees like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
AT Employee
  id: 3
  firstName: "Marcus"
  lastName: "O'Brien"
  title: "Senior Software Engineer"
  startDate: "3/14/2021"
  department: 
    id: 1,
    value: "Engineering"
AT Employee
  id: 6
  firstName: "Marianne"
  lastName: "Kowalski"
  title: "Business Intelligence Analyst"
  startDate: "2/10/2018"
  department: 
    id: 1,
    value: "Engineering"

Feature compatibility

The table below lists this function's compatibility with various features in Appian.
Feature Compatibility Note
Portals Compatible
Offline Interfaces Partially compatible

Can be used with offline interfaces if loaded at the top of the interface.

Sync-Time Custom Record Fields Incompatible
Real-Time Custom Record Fields Incompatible

Custom record fields that evaluate in real time must be configured using one or more Custom Field functions.

Process Reports Incompatible

Cannot be used to configure a process report.

Process Events Partially compatible

If autoscale is enabled, can be used to configure a supported process event node (such as a start event or timer event).

Process Autoscaling Compatible

Can be used in autoscaled processes.

Event Consumer Filter Conditions Incompatible

Cannot be used in filter conditions.

Event Consumer Event Handlers Incompatible

Cannot be used in event handler expressions.

Feedback