> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/reports/filters-and-parameters.md).

# Filters and parameters

The condition editor behind the wizard, the designer and the view builder — match modes and custom logic, every operator by field type, related-record conditions, the "Ask when running" switch, and wh

## What this is, and when you need it

A filter decides which rows a report includes. The same condition editor appears in three places: the wizard's [Filters step](/administration-guide/reports/create-a-report.md#wizard-filters), the designer's [Data source tab](/administration-guide/reports/design-a-report.md#designer-data-source-entities) when the report is built from entities, and the [view builder](/administration-guide/reports/views-and-sql-sources.md#builder-primary-entity). This page explains the editor once: how conditions combine, what each operator means on each field type, how to filter on related records, and what **Ask when running** does.

You do not need this page to filter on an SQL (Structured Query Language) data source: its statement decides the rows, and its [parameters](/administration-guide/reports/views-and-sql-sources.md#sql-parameters) are declared on the source, not here.

## The condition editor <a href="#filter-editor" id="filter-editor"></a>

The editor is one block, headed **Filters**, with three parts from top to bottom: the [match mode](#filter-match-mode) bar, which says how the conditions combine; the list of [condition rows](#filter-condition-row), each a field, an operator and a value, numbered in custom-logic mode; and the two buttons that add a row, **Add condition** for a condition on a field and **Add related-record condition** for a test on records of another entity. With no rows the block reads *No filters. All rows are included.*

Everything you do in the editor is held in the browser until the surrounding wizard step, the designer or the view is saved; the server then validates the whole definition, see [Validation codes](#filter-validation-codes).

## Where the filters apply <a href="#filter-where" id="filter-where"></a>

| Where you edit                                                      | What the conditions filter                                                                                                                                                   |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Wizard Filters step, designer Data source tab (built from entities) | The report's own data source. These are the only filters the report has.                                                                                                     |
| View builder                                                        | The view. Every report that reads the view inherits them and cannot remove them.                                                                                             |
| Wizard Filters step, when the report reads a view                   | Conditions added on top of the view's. A row must pass the view's filters **and** the report's. The view's own conditions are shown read-only under **Filters of the view**. |

With no conditions the editor reads *No filters. All rows are included.*

Conditions are evaluated by the backend that holds the entity: as SQL against the source database for Database entities, as a search query for OpenSearch entities. The operators below are the same on both, with the exceptions noted.

## Match mode <a href="#filter-match-mode" id="filter-match-mode"></a>

The bar above the conditions sets how they combine:

| Mode                           | Meaning                                        |
| ------------------------------ | ---------------------------------------------- |
| Match all of the filters below | Every condition must hold (AND). The default.  |
| Match any of the filters below | At least one condition must hold (OR).         |
| Custom logic                   | You write how the numbered conditions combine. |

### Custom logic <a href="#filter-custom-logic" id="filter-custom-logic"></a>

In custom mode each condition shows its number, and the expression box takes a formula such as `1 AND (2 OR 3)`, with `NOT` and parentheses allowed. The status under the box reads *Logic is valid* or names the problem. The rules:

* Every condition must appear exactly once. *Condition 2 is not used* and *Condition 5 does not exist* are both errors.
* `AND` and `OR` may not be mixed on one level: write `1 AND (2 OR 3)`, not `1 AND 2 OR 3`.
* The expression is at most 1,000 characters and uses only numbers, `AND`, `OR`, `NOT` and parentheses; anything else is reported with its position.

The wizard's **Next**, the designer's **Save** and the view's **Save** all wait until the expression is valid.

## A condition row <a href="#filter-condition-row" id="filter-condition-row"></a>

A condition is a field, an operator and a value. The field list holds every field of the main entity and of each related entity that the catalog marks filterable; the operator list depends on the field's type and opens on the first operator for that type; the value control depends on the operator:

| Value control                                        | When                                                                     |
| ---------------------------------------------------- | ------------------------------------------------------------------------ |
| Text box                                             | Text and number fields, single-value operators.                          |
| Comma-separated text, placeholder `Value 1, Value 2` | **in list** and **not in list**. See [list values](#filter-list-values). |
| Two boxes joined by *and*                            | **between**. See [between](#filter-between).                             |
| Date picker                                          | Date and date-and-time fields, except **in the last N days**.            |
| A number labelled *Days*                             | **in the last N days**.                                                  |
| Yes / No                                             | Yes/No fields.                                                           |
| Nothing                                              | **is empty** and **is not empty**.                                       |

Each row ends with a remove button. The row of a date field also carries the [Ask when running](#param-ask-when-running) switch.

## Operators by field type <a href="#filter-operators" id="filter-operators"></a>

The catalog types every field as text, number, Yes/No, date or date and time. The operator list offers only what the type supports; the server's validator refuses anything else with `OPERATOR_NOT_ALLOWED`.

| Operator           | Text | Number | Yes/No | Date, date and time | Notes                                                                                       |
| ------------------ | ---- | ------ | ------ | ------------------- | ------------------------------------------------------------------------------------------- |
| equals             | yes  | yes    | yes    | yes                 | Exact match.                                                                                |
| not equals         | yes  | yes    | yes    | yes                 | A row whose field is empty is not matched by either equals or not equals; use **is empty**. |
| greater than       | —    | yes    | —      | yes                 |                                                                                             |
| at least           | —    | yes    | —      | yes                 | Greater than or equal.                                                                      |
| less than          | —    | yes    | —      | yes                 |                                                                                             |
| at most            | —    | yes    | —      | yes                 | Less than or equal.                                                                         |
| in list            | yes  | yes    | —      | —                   | See [list values](#filter-list-values).                                                     |
| not in list        | yes  | yes    | —      | —                   | See [list values](#filter-list-values).                                                     |
| contains           | yes  | —      | —      | —                   | The text appears anywhere in the value.                                                     |
| starts with        | yes  | —      | —      | —                   | The text is the beginning of the value.                                                     |
| between            | —    | yes    | —      | yes                 | Both ends included. See [between](#filter-between).                                         |
| in the last N days | —    | —      | —      | yes                 | See [in the last N days](#filter-in-last-days).                                             |
| is empty           | yes  | yes    | yes    | yes                 | See [empty values](#filter-empty).                                                          |
| is not empty       | yes  | yes    | yes    | yes                 | See [empty values](#filter-empty).                                                          |

A date value is accepted on a date-and-time field; the comparison then uses the start of that day. Text comparisons behave as the source database does: on most installations **equals** on a text field ignores case, because the database collation does.

### List values <a href="#filter-list-values" id="filter-list-values"></a>

**in list** and **not in list** take several values in one box, separated by commas: `ACTIVE, PENDING, LOCKED`. Spaces around a comma are ignored. The row matches when the field equals any one of the values (or none of them, for **not in list**). A list cannot be combined with a [parameter](#param-ask-when-running): parameters are for date fields.

For the running example, Dana could widen the contractor filter to **Employee type** *in list* `CONTRACTOR, INTERN` without adding a second condition.

### Between <a href="#filter-between" id="filter-between"></a>

**between** takes two values, a lower and an upper bound, and both bounds are included: **Start date** *between* `2026-01-01` and `2026-03-31` keeps the whole first quarter. For a date-and-time field, a date as the upper bound means the start of that day, so a membership that started at 10:00 on 31 March is not in the range above; use 1 April, or **at most** with the time, instead.

### In the last N days <a href="#filter-in-last-days" id="filter-in-last-days"></a>

**in the last N days** keeps the rows whose date is within the last N whole days before the moment the report runs. N is a positive whole number typed in the *Days* box. Because the window is counted back from the run clock, the same condition means something new on every scheduled run: **Last login** *in the last 60 days* on a Monday schedule always means "since the Monday eight and a half weeks ago". That is why it is the operator the [Ask when running](#param-ask-when-running) switch uses, and the operator to prefer over **at least** with a fixed date for any report that runs more than once.

### Empty values <a href="#filter-empty" id="filter-empty"></a>

**is empty** keeps the rows whose field has no value; **is not empty** keeps the others. These are the only operators that see an empty value: **not equals** `X` does not keep the rows where the field is empty, because an empty value is neither equal nor unequal to anything. To list users with no last date, use **Last date** *is empty*, not *not equals*.

## Related-record conditions <a href="#filter-related-records" id="filter-related-records"></a>

**Add related-record condition** adds a condition on records of another entity, reached through a relationship, without adding that entity to the report: "users who hold at least one role of type X", "roles no user holds". The row has:

| Control                      | Description                                                                                                                                                                                                                                                  |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Related records              | **has matching** or **has no matching**.                                                                                                                                                                                                                     |
| Relationship                 | A relationship from the main entity, or from a related entity already in the data source, to the entity to test. An entity that is already part of the data source is greyed out with *Already in the data source*: join it on the Data source step instead. |
| Related … records must match | A nested editor with its own conditions and match mode on the fields of the related entity. Leave it empty and *Any related record counts*: the condition is then "has at least one" or "has none".                                                          |

A related-record condition never multiplies rows: a user with five matching roles is one row. That is the difference from joining the entity, which makes one row per match. The button is missing, and the editor reads *No relationship can be followed from here*, when the catalog has no relationship from the entities in the data source. OpenSearch entities have no relationships, so an OpenSearch data source never offers the button.

For the running example, a cleaner way to express "contractors who hold a role" without the *Status equals ACTIVE* condition on User role membership is a related-record condition: **User** *has matching* **User role membership** where *Status equals ACTIVE*. The report then lists each contractor once no matter how many roles they hold; for the per-role count the join is still needed.

## Nested groups <a href="#filter-nested-groups" id="filter-nested-groups"></a>

The editor shows one flat list of conditions. A definition saved through the API, or by an earlier version, can hold a group inside a group; the editor shows such a group as *Nested group (3 conditions)* with a **Remove group** button and nothing else. It still filters as saved. To change what is inside, remove it and rebuild the conditions on the top level; for AND inside OR, use [custom logic](#filter-custom-logic).

Inside the read-only **Filters of the view** block of the wizard, a related-record condition of the view appears the same way, as *Related rows (n)* marked *Read-only*.

## Ask when running <a href="#param-ask-when-running" id="param-ask-when-running"></a>

A date or date-and-time condition carries an **Ask when running** switch. Turning it on turns the condition into a parameterised window:

<figure><img src="https://2965242200-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0uHWHRgcad6P03ehqgmX%2Fuploads%2Fgit-blob-aaef6745651f6ffc52230b016bc32d6bd9258ce4%2Freport-wizard-02b-ask-when-running.png?alt=media" alt="A date condition on User role membership › Start date with Ask when running switched on: the operator reads in the last N days, the Parameter badge shows start_date and the days field holds 30"><figcaption></figcaption></figure>

* The operator becomes **in the last N days** and its selector is disabled.
* A badge *Parameter: last\_login* appears, named after the field; the name is made unique when the field is used twice.
* A **Days before the run** box appears for the number the window starts with, and a **Parameter name** box for the name.
* The report declares a required number parameter with that name and default. The parameter belongs to the report (or to the view, when set in the view builder).

The hint under the row reads *Keeps the rows whose Last login is within the last N days before the run. N is asked when the report runs and starts at the number entered here.* Read the next two sections for what "asked" means in this release.

The switch appears only on date and date-and-time fields, and only in editors that allow parameters (the wizard, the designer and the view builder; not inside a related-record condition). A condition on another field type that already references a parameter, saved by an earlier build, still shows the switch so that it can be turned off; turning it on again is not offered.

### Days before the run <a href="#param-days" id="param-days"></a>

The number is required: a whole number, 1 or more. While it is missing, the row shows *Enter the number of days: a whole number, 1 or more* in red, the wizard's **Next** is disabled on the Filters step, and the designer's and the view's **Save** are refused with the code `DAYS_REQUIRED` (*This condition asks for a number of days when the report runs. Enter the number it starts with*). The number is stored as the parameter's default and is the value every run uses; see [What happens at run time](#param-at-run-time).

For the running example's clone of the Inactive users template, Dana switches **Last login** *in the last 90 days* to **Ask when running** and types `60`.

### Parameter name <a href="#param-name" id="param-name"></a>

A letter followed by up to 63 letters, digits or underscores (`[A-Za-z][A-Za-z0-9_]{0,63}`). The name is how the value is referenced inside the definition (`{{param.last_login}}`), how it appears in the Preview prompt and in audit entries, and how a schedule would store a value for it. Renaming is harmless until a schedule stores values; today no schedule does.

### What happens at run time <a href="#param-at-run-time" id="param-at-run-time"></a>

A parameter's value is resolved, in this order: a value typed in the details-page **Preview**; then values stored on the report's layout; then the parameter's own default. In this release the user interface never writes layout values, and the schedule form has no parameter inputs, so in practice:

| Where the report runs         | Which value is used                                                                                                                                                                                             |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Preview on the details page   | The preview prompts for a required parameter that has **no** default. A parameter created by **Ask when running** always has one (the days you typed), so the preview does not prompt for it and uses the days. |
| Run, Export CSV, Export Excel | The parameter's default. No prompt.                                                                                                                                                                             |
| A scheduled run               | The parameter's default. The schedule stores no values of its own.                                                                                                                                              |

The consequence for an **Ask when running** condition: the days you typed are the window of every run, and nobody is asked. The prompt the hint text promises is not in this release. The consequence for any other required parameter without a default, such as a required parameter on an SQL data source the report reads: Preview asks for it, but **Run**, **Export** and a schedule have nothing to send, so the run fails validation and the wizard refuses to schedule the report (*This report asks for … when it runs. A scheduled run cannot ask for a value*). Give such a parameter a default, or replace the condition with **in the last N days**.

## Validation codes <a href="#filter-validation-codes" id="filter-validation-codes"></a>

The editor checks what it can while you type. The server validates the whole definition when the wizard creates the report, when the designer or the view saves, when **Validate** runs in the builder, and again before every run. A refused definition shows one line per problem with one of these codes:

| Code                              | What it means                                                                                                                                                                                                         |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DAYS_REQUIRED`                   | An **Ask when running** condition has no number of days.                                                                                                                                                              |
| `CROSS_BACKEND_JOIN`              | *This entity is stored in another backend or database. Only entities from the same database can be combined in one data source.* See [the backend rule](/administration-guide/reports/overview.md#rules-one-backend). |
| `MULTIPLE_INDEXES`                | *A data source can read only one OpenSearch entity. Remove the other one or choose another relationship.*                                                                                                             |
| `DUPLICATE_OBJECT`                | *This entity is already part of the data source. An entity can be used only once.*                                                                                                                                    |
| `AMBIGUOUS_JOIN`                  | *This entity is connected to the data source by more than one relationship. Choose the relationship to use.*                                                                                                          |
| `NO_ASSOCIATION`                  | *No relationship connects this entity to the data source here.*                                                                                                                                                       |
| `OPERATOR_NOT_ALLOWED`            | The operator is not valid for the field's type; for instance **contains** on a number.                                                                                                                                |
| `TYPE_MISMATCH`                   | The value cannot be read as the field's type: text in a number condition, a malformed date, a date parameter on a number field.                                                                                       |
| `NOT_FILTERABLE`                  | The catalog does not allow conditions on this field.                                                                                                                                                                  |
| `INVALID_LOGIC`                   | The custom logic expression is malformed, skips a condition or mixes AND and OR without parentheses.                                                                                                                  |
| `UNDECLARED_PARAMETER`            | A condition references `{{param.x}}` and no parameter `x` is declared. Only reachable through the API.                                                                                                                |
| `INVALID_PARAMETER`               | A parameter's name breaks the pattern, its default does not match its type, or a required parameter has no value at run time.                                                                                         |
| `LIMIT_EXCEEDED`                  | The definition is over a limit: more than 50 conditions, nesting deeper than 5 levels, or more than 4 references in a logic expression. See [Limits](/administration-guide/reports/overview.md#limits).               |
| `UNKNOWN_FIELD`, `UNKNOWN_OBJECT` | A field or entity in the definition no longer exists in the catalog, usually after an upgrade. Remove it.                                                                                                             |
| `NOT_GROUPED`                     | A field is neither grouped nor summarised in a report that groups. See [the grouping rule](/administration-guide/reports/overview.md#rules-grouping).                                                                 |

## When it goes wrong

| Symptom                                                                | Likely cause                                                                                                                                                               |
| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The operator I need is not in the list.                                | The field's type does not support it; see [the operator table](#filter-operators). For "newer than a date" on a schedule, use **in the last N days**.                      |
| *Logic is valid* never appears.                                        | The expression skips a condition number, uses one twice, mixes AND and OR without parentheses, or contains a word other than AND, OR, NOT. The message names the position. |
| A row I expect is missing, and the condition is **not equals**.        | The field is empty on that row; **not equals** does not match empty values. Add **is empty** with *Match any*.                                                             |
| The report returns one row per role instead of one per user.           | The entity is joined, not tested. Use a related-record condition for "has at least one".                                                                                   |
| **Add related-record condition** is missing.                           | No relationship leads from the entities in the data source, or the data source is an OpenSearch entity.                                                                    |
| The Preview asks for a value but **Run** fails with a parameter error. | A required parameter has no default; only the Preview prompts. Give it a default or use **in the last N days**. See [What happens at run time](#param-at-run-time).        |
| **Ask when running** does not appear on a condition.                   | The field is not a date, or the editor is inside a related-record condition.                                                                                               |
| The same report run twice gives different rows.                        | **in the last N days** is counted from each run's clock. That is by design.                                                                                                |

## Related

* [Create a report](/administration-guide/reports/create-a-report.md#wizard-filters) — where the editor appears in the wizard
* [Design a report](/administration-guide/reports/design-a-report.md#designer-data-source-entities) — the editor on an existing report
* [Views and SQL data sources](/administration-guide/reports/views-and-sql-sources.md) — filters on a view, parameters on an SQL source
* [Report builder overview](/administration-guide/reports/overview.md#limits) — the limits behind `LIMIT_EXCEEDED`
* [Run a report and download the file](/administration-guide/reports/run-and-download.md#preview) — the Preview that prompts


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/reports/filters-and-parameters.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
