> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracecat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lookups

## `core.table.lookup`

Get a single row from a table corresponding to the given column and value.

### Inputs

<ParamField path="column" type="string" required>
  The column to lookup the value in.
</ParamField>

<ParamField path="table" type="string" required>
  The table to lookup the value in.
</ParamField>

<ParamField path="value" type="any" required>
  The value to lookup.
</ParamField>

### Examples

**Look up rows**

```yaml theme={null}
- ref: lookup_row
  action: core.table.lookup
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: row_exists
  action: core.table.is_in
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: lookup_many_rows
  action: core.table.lookup_many
  args:
    table: asset_inventory
    column: owner
    value: secops
    limit: 25
```

## `core.table.is_in`

Check if a value exists in a table column.

### Inputs

<ParamField path="column" type="string" required>
  The column to check in.
</ParamField>

<ParamField path="table" type="string" required>
  The table to check.
</ParamField>

<ParamField path="value" type="any" required>
  The value to check for.
</ParamField>

### Examples

**Look up rows**

```yaml theme={null}
- ref: lookup_row
  action: core.table.lookup
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: row_exists
  action: core.table.is_in
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: lookup_many_rows
  action: core.table.lookup_many
  args:
    table: asset_inventory
    column: owner
    value: secops
    limit: 25
```

## `core.table.lookup_many`

Get multiple rows from a table corresponding to the given column and values.

### Inputs

<ParamField path="column" type="string" required>
  The column to lookup the value in.
</ParamField>

<ParamField path="table" type="string" required>
  The table to lookup the value in.
</ParamField>

<ParamField path="value" type="any" required>
  The value to lookup.
</ParamField>

<ParamField path="limit" type="integer">
  The maximum number of rows to return.

  Default: `100`.
</ParamField>

### Examples

**Look up rows**

```yaml theme={null}
- ref: lookup_row
  action: core.table.lookup
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: row_exists
  action: core.table.is_in
  args:
    table: asset_inventory
    column: hostname
    value: ${{ TRIGGER.hostname }}
- ref: lookup_many_rows
  action: core.table.lookup_many
  args:
    table: asset_inventory
    column: owner
    value: secops
    limit: 25
```

## `core.table.search_rows`

Search for rows in a table with optional filtering.

### Inputs

<ParamField path="table" type="string" required>
  The table to search in.
</ParamField>

<ParamField path="cursor" type="string | null">
  Cursor for pagination.

  Default: `null`.
</ParamField>

<ParamField path="end_time" type="string | null">
  Filter rows created before this time.

  Default: `null`.
</ParamField>

<ParamField path="limit" type="integer">
  The maximum number of rows to return.

  Default: `100`.
</ParamField>

<ParamField path="paginate" type="boolean">
  If true, return cursor pagination metadata along with items.

  Default: `false`.
</ParamField>

<ParamField path="reverse" type="boolean">
  Reverse pagination direction.

  Default: `false`.
</ParamField>

<ParamField path="search_term" type="string | null">
  Text to search for across all text and JSONB columns.

  Default: `null`.
</ParamField>

<ParamField path="start_time" type="string | null">
  Filter rows created after this time.

  Default: `null`.
</ParamField>

<ParamField path="updated_after" type="string | null">
  Filter rows updated after this time.

  Default: `null`.
</ParamField>

<ParamField path="updated_before" type="string | null">
  Filter rows updated before this time.

  Default: `null`.
</ParamField>

### Examples

**Search table rows**

```yaml theme={null}
- ref: search_rows
  action: core.table.search_rows
  args:
    table: asset_inventory
    search_term: database
    limit: 50
    paginate: true
```

## `core.table.aggregate_rows`

Filter, group, and summarize table rows. Returns groups and a truncated flag indicating whether more groups exist than the requested limit.

The example groups alerts by source and hour, then calculates the
alert count, total bytes, and median duration for each group.

Before running it, create an `alerts` table with these columns:

* `source`: TEXT.
* `disposition`: TEXT.
* `bytes_out`: INTEGER.
* `duration_ms`: NUMERIC.

Use `ACTIONS.bytes_by_source_hourly.result.groups` to read the results.
If `ACTIONS.bytes_by_source_hourly.result.truncated` is `true`,
the result reached the group limit and omitted some groups.

### Inputs

<ParamField path="group_by" type="array[string | object]" required>
  Choose how to split rows into groups. Use up to 3 fields, or `[]` for one total across all matching rows.

  Supply a field name such as `source`, or an object with `field` and optional `bucket`, `timezone`, and `alias`. For example: \['source', \{'field': 'created\_at', 'bucket': 'hour'}]. An alias names the field in the result; it defaults to the field name. All output names must be unique and at most 63 UTF-8 bytes.

  Fields you can group by:

  * TEXT, SELECT, INTEGER, NUMERIC, and BOOLEAN columns.
  * DATE and TIMESTAMPTZ columns, including the system fields `created_at` and `updated_at`. These require a `bucket`: `hour`, `day`, `week`, or `month`. Weeks start on Monday.

  JSONB, MULTI\_SELECT, `id`, and internal columns are unsupported.

  Date and time settings:

  * Timestamps accept an IANA timezone name, such as `America/New_York`. The default is `UTC`; results always contain UTC timestamps.
  * DATE fields return `YYYY-MM-DD`. They do not accept a timezone, and even an `hour` bucket retains only date precision.

  How group values appear in results:

  * Missing values share one `null` group.
  * TEXT and SELECT values use only the first 256 characters. Values with the same prefix merge into one group.
  * NUMERIC values appear as exact decimal strings.
</ParamField>

<ParamField path="table" type="string" required>
  The name of the workspace table to aggregate.
</ParamField>

<ParamField path="aggs" type="array[object] | null">
  Choose what to calculate for each group. Omit this input to count rows. Supply up to 8 calculations; an empty list is invalid.

  Each calculation is an object with `function`, optional `field`, and optional `alias`. For example: \[\{'function': 'sum', 'field': 'bytes\_out', 'alias': 'total\_bytes'}].

  Available calculations:

  * `count`: Count rows when you omit `field`, or count non-null values when you supply it.
  * `count_distinct`: Count different non-null values.
  * `sum`, `mean`, `median`: Calculate the total, average, or middle value.
  * `min`, `max`: Return the smallest or largest value.

  Every function except `count` requires a field. Numeric columns support all functions. Text and date/time columns support `count`, `count_distinct`, `min`, and `max`. BOOLEAN and SELECT columns support only `count` and `count_distinct`.

  Naming and number formats:

  * Use `alias` to name a result, such as `total_bytes`. Otherwise the name is `count` or `function_field`. All output names must be unique and at most 63 UTF-8 bytes.
  * Counts are integers. INTEGER/NUMERIC sums, all means and medians, and NUMERIC min/max use floating-point numbers and can lose precision. NUMERIC grouping values remain exact decimal strings.

  Default: `null`.
</ParamField>

<ParamField path="filters" type="object | null">
  Choose which rows to include before grouping. Omit this input to include all rows.

  Write one condition as \{'field': 'amount', 'op': 'gte', 'value': 10}. Combine conditions with \{'and': \[...]}, \{'or': \[...]}, or \{'not': \{...}}.

  Choose an operator supported by the column type:

  * TEXT: `eq`, `ne`, `in`, `not_in`, `is_null`, `contains`, and `starts_with`. Only `contains` and `starts_with` ignore case and match literal text; `eq`, `ne`, `in`, and `not_in` are case-sensitive.
  * INTEGER and NUMERIC: `eq`, `ne`, `in`, `not_in`, `gt`, `gte`, `lt`, `lte`, and `is_null`.
  * DATE and TIMESTAMPTZ: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, and `is_null`.
  * SELECT: `eq`, `ne`, `in`, `not_in`, and `is_null`.
  * BOOLEAN: `eq`, `ne`, and `is_null`.

  Supply a list for `in` or `not_in`. Omit `value` for `is_null`. Use strings for exact decimals and ISO-formatted dates or timestamps.

  `ne` and `not_in` exclude missing values. An empty `not_in` list matches all rows; an empty `in` list matches none.

  Filters allow up to 4 levels of nesting, 50 conditions, and 1000 total values. The server validates the request when the action runs.

  Default: `null`.
</ParamField>

<ParamField path="limit" type="integer | null">
  Set the maximum number of groups to return. Use at least 1, up to your server's configured maximum (normally 1000). Omit this input to use the server default (normally 100).

  If more groups exist, the result sets `truncated` to `true`. There is no next-page cursor.

  Default: `null`.
</ParamField>

<ParamField path="min_count" type="integer | null">
  Only return groups with at least this many rows (minimum 1).

  Default: `null`.
</ParamField>

<ParamField path="order_by" type="string | null">
  Choose a group or calculation output name to sort by, including any alias you set.

  If omitted, results sort by the first date/time bucket, or by the first calculation when there is no date/time bucket.

  Default: `null`.
</ParamField>

<ParamField path="sort" type="string | null">
  Use `asc` for ascending order or `desc` for descending order.

  If omitted, the direction is `asc` when the action automatically sorts by a date/time bucket. Otherwise it is `desc`, including when you set `order_by` yourself. Missing values sort last; group values break ties.

  Default: `null`.
</ParamField>

### Examples

**Sum bytes by source and hour**

```yaml theme={null}
- ref: bytes_by_source_hourly
  action: core.table.aggregate_rows
  args:
    table: alerts
    filters:
      and:
        - field: disposition
          op: ne
          value: benign
        - field: created_at
          op: gte
          value: "2026-08-31T00:00:00Z"
    group_by:
      - source
      - field: created_at
        bucket: hour
    aggs:
      - function: count
      - function: sum
        field: bytes_out
        alias: total_bytes
      - function: median
        field: duration_ms
    limit: 200
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.