> ## 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.

Group rows and calculate counts, totals, or averages in your workflow.
Create an `alerts` table with `source` (TEXT), `disposition` (TEXT),
and `bytes_out` (INTEGER) columns before running this example.
Use `[]` for `group_by` to calculate a single total across matching rows.

Read the summaries from `ACTIONS.bytes_by_source_hourly.result.groups`.
If `truncated` is `true`, more groups matched than the result limit.
Omit `limit` to use your server's default, normally 100 groups.

### Inputs

<ParamField path="group_by" type="array[string | object]" required>
  Up to 3 grouping fields, as names or objects with field, bucket, timezone, and alias. Example: \['category', \{'field': 'created\_at', 'bucket': 'day'}]. Use \[] for a single grand total. DATE and TIMESTAMPTZ fields require an hour/day/week/month bucket; weeks start Monday. Timestamp buckets accept an IANA timezone (default UTC) and return UTC instants. DATE buckets return YYYY-MM-DD, reject timezone, and have only date precision even with hour. System created\_at/updated\_at are available. TEXT, SELECT, INTEGER, NUMERIC, and BOOLEAN can group directly. JSONB, MULTI\_SELECT, id, and internal columns are unsupported. Null keys form a group. TEXT/SELECT keys use the first 256 characters; longer values with the same prefix merge. NUMERIC keys are exact decimal strings. Aliases default to field names and must be unique across all outputs and at most 63 UTF-8 bytes.
</ParamField>

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

<ParamField path="aggs" type="array[object] | null">
  Up to 8 calculations: \{function, field, alias}. Functions: count, count\_distinct, sum, mean, median, min, max. Example: \[\{'function': 'sum', 'field': 'amount', 'alias': 'total'}]. None defaults to count; \[] is invalid. count without field counts rows; count with field counts non-null values. Other functions require field. Numbers support every function; TEXT and temporal fields support count, count\_distinct, min, max; BOOLEAN/SELECT support count and count\_distinct. Aliases default to count or function\_field and must be unique and at most 63 UTF-8 bytes. Counts are integers. INTEGER/NUMERIC sums, all means/medians, and NUMERIC min/max are floating-point JSON numbers, with possible precision loss; NUMERIC grouping keys remain exact strings.

  Default: `null`.
</ParamField>

<ParamField path="filters" type="object | null">
  Filter rows before grouping. Use \{field, op, value}, or combine conditions with \{'and': \[...]}, \{'or': \[...]}, or \{'not': \{...}}. Example: \{'field': 'amount', 'op': 'gte', 'value': 10}. Operators: eq, ne, in, not\_in, gt, gte, lt, lte, contains, starts\_with, is\_null. in/not\_in take lists; is\_null takes no value. TEXT supports eq/ne/in/not\_in/is\_null and case-insensitive literal contains/starts\_with. Numbers support comparisons and membership; dates support comparisons; SELECT supports eq/ne/in/not\_in/is\_null; BOOLEAN supports eq/ne/is\_null. ne/not\_in exclude null values, except empty not\_in matches all rows; empty in matches none. Use strings for exact decimal values and ISO strings for dates and timestamps. Maximum depth 4, 50 conditions, and 1000 total values. None means no filtering. Shapes are validated at runtime.

  Default: `null`.
</ParamField>

<ParamField path="limit" type="integer | null">
  Maximum groups to return, at least 1 and subject to the server's configured maximum (normally 1000). Omit to use the server default (normally 100). Excess groups set truncated.

  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">
  Group or calculation output name to sort by. Defaults to the first time bucket if present, otherwise the first calculation.

  Default: `null`.
</ParamField>

<ParamField path="sort" type="string | null">
  Sort direction. Defaults to asc when automatically ordering by a time bucket; otherwise desc, including when order\_by is explicit. Nulls sort last; group keys 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
```
