Skip to content
Browse documentation
Working with data

Inspect your data

Let AVA discover the structure, inspect statistics when useful, then add business meaning.

Start with this small order table. The Define data semantics guide uses these same six rows.

order_idregionstatusamountrefund_amountordered_at
1Eastpaid120202026-01-03
2Eastrefunded80802026-01-04
3Eastpending20002026-01-05
4Westpaid90302026-01-06
5Eastpaid50null2026-01-07
6Westcancelled50002026-01-08
Load this table as inline JSON

With ava configured, load the rows below. The default DuckDB engine exposes them as a model named data.

typescript
const orders = [
  { order_id: 1, region: 'East', status: 'paid', amount: 120, refund_amount: 20, ordered_at: '2026-01-03' },
  { order_id: 2, region: 'East', status: 'refunded', amount: 80, refund_amount: 80, ordered_at: '2026-01-04' },
  { order_id: 3, region: 'East', status: 'pending', amount: 200, refund_amount: 0, ordered_at: '2026-01-05' },
  { order_id: 4, region: 'West', status: 'paid', amount: 90, refund_amount: 30, ordered_at: '2026-01-06' },
  { order_id: 5, region: 'East', status: 'paid', amount: 50, refund_amount: null, ordered_at: '2026-01-07' },
  { order_id: 6, region: 'West', status: 'cancelled', amount: 500, refund_amount: 0, ordered_at: '2026-01-08' },
];
 
await ava.source({ type: 'json', options: { data: orders } });

Schema: the structure AVA discovers

typescript
const schema = await ava.schema();
console.log(schema.models[0]);

For this table, the discovered model is:

json
{
  "name": "data",
  "tableReference": { "catalog": "memory", "schema": "main", "table": "data" },
  "columns": [
    { "name": "order_id", "type": "BIGINT", "notNull": false },
    { "name": "region", "type": "VARCHAR", "notNull": false },
    { "name": "status", "type": "VARCHAR", "notNull": false },
    { "name": "amount", "type": "BIGINT", "notNull": false },
    { "name": "refund_amount", "type": "BIGINT", "notNull": false },
    { "name": "ordered_at", "type": "DATE", "notNull": false }
  ]
}

This is your automatically discovered structural starting point. You do not write it by hand. Types and source qualifiers depend on the engine; database sources may also expose declared keys and relationships. notNull: false means there is no declared non-null constraint, not that a null was found.

AVA also discovers schema when analysis needs it, so calling schema() yourself is optional.

Profile: statistics AVA computes

typescript
const profile = await ava.profile({
  metrics: ['row_count', 'null_count', 'min', 'max'],
});

Among the results for the same table:

ObservationWhere it appears in ProfileValue
Number of rowsModel metrics.row_count6
Missing refundsrefund_amount column's metrics.null_count1
Smallest order amountamount column's metrics.min50
Largest order amountamount column's metrics.max500

Profiling is optional, requires engine support, and can scan the data. It does not call an LLM. See metric options for other statistics.

Semantic: the meaning you add

The table contains paid, refunded, pending, and cancelled orders. Which should count as revenue? That is a rule you supply:

typescript
await ava.semantic(undefined, () => ({
  description: 'Amounts are USD. Revenue counts paid and refunded orders, subtracts refunds, and excludes pending and cancelled orders. A missing refund is zero.',
  cubes: [{
    name: 'sales',
    baseObject: 'data',
    measures: [{
      name: 'net_revenue',
      expression: "SUM(CASE WHEN status IN ('paid', 'refunded') THEN amount - COALESCE(refund_amount, 0) ELSE 0 END)",
      type: 'DOUBLE',
    }],
    dimensions: [{ name: 'region', expression: 'region', type: 'VARCHAR' }],
  }],
}));

description explains the business rule. The sales cube names its source (data), revenue calculation (measures), and region grouping (dimensions). The discovered columns remain available without repeating them; the cube guides query generation and does not create a database object.

Continue to Define data semantics for the full example and corresponding SQL result: East 150 USD, West 60 USD . Field formats, manual overrides, and update rules are in the API reference.