> hypequery

Metrics

Attach named KPIs and derived calculations to datasets.

Metrics are named KPI handles attached to a dataset. They are the reusable values you expose to APIs, dashboards, agents, and MCP clients.

Measures define raw aggregations inside a dataset. Metrics promote those measures into named business concepts.

const revenue = Orders.metric('revenue', { measure: 'revenue' });

await analytics.execute(revenue, {
  dimensions: ['country'],
  filters: [eq('status', 'completed')],
  limit: 10,
});

Base metrics

Base metrics point at one measure from the same dataset.

const revenue = Orders.metric('revenue', {
  measure: 'revenue',
  label: 'Total Revenue',
  description: 'Total order amount before refunds.',
});

const orderCount = Orders.metric('orderCount', {
  measure: 'orderCount',
  label: 'Order Count',
});

If label or description are omitted, the metric inherits them from the referenced measure when available.

Base metric options

type BaseMetricConfig = {
  measure: string;
  label?: string;
  description?: string;
};
OptionUse it for
measureThe dataset measure this metric exposes
labelHuman-readable display text for docs, UIs, and agents
descriptionLonger metadata for generated docs, UIs, and agents

Derived metrics

Derived metrics compose base metrics from the same dataset using formulas.

import { divide, nullIfZero } from '@hypequery/datasets';

const averageOrderValue = Orders.metric('averageOrderValue', {
  uses: { revenue, orderCount },
  formula: ({ revenue, orderCount }) =>
    divide(revenue, nullIfZero(orderCount)),
  label: 'Average Order Value',
});

Derived metrics can only use base metrics from the same dataset. They cannot reference metrics from another dataset, and they cannot be derived from another derived metric.

Derived metric options

type DerivedMetricConfig = {
  uses: Record<string, BaseMetricRef>;
  formula: (inputs: Record<string, string>) => FormulaExpr;
  label?: string;
  description?: string;
};
OptionUse it for
usesThe base metric refs available to the formula
formulaA symbolic formula that combines those base metrics
labelHuman-readable display text for docs, UIs, and agents
descriptionLonger metadata for generated docs, UIs, and agents

Formula helpers include:

  • divide(a, b)
  • multiply(a, b)
  • add(a, b)
  • subtract(a, b)
  • nullIfZero(value)
  • coalesce(...)
  • round(...)

Formula helpers are symbolic. They build expressions that hypequery can plan and execute; they are not raw SQL strings.

Metric queries vs dataset queries

Use metric queries when you want to expose one named KPI contract.

const revenue = Orders.metric('revenue', { measure: 'revenue' });

await analytics.execute(revenue, {
  dimensions: ['country'],
  filters: [eq('status', 'completed')],
  orderBy: [{ field: 'revenue', direction: 'desc' }],
  limit: 10,
});

Use dataset queries when callers need an ad hoc selection of dimensions and measures from the same dataset.

await analytics.execute(Orders, {
  dimensions: ['country', 'status'],
  measures: ['revenue', 'orderCount'],
  filters: [eq('status', 'completed')],
});

Both paths use the same dataset definition and validation rules. Metrics are better for reusable product concepts; dataset queries are better for same-dataset exploration.

Time grains

When the dataset has a timeKey, metrics can be grained by time.

const monthlyRevenue = revenue.by('month');

await analytics.execute(monthlyRevenue, {
  dimensions: ['country'],
});

Supported grains are day, week, month, quarter, and year.

MCP metadata

Named metrics are exposed through MCP get_dataset_schema. Use label and description to make metric intent clear to agents and UIs.

const averageOrderValue = Orders.metric('averageOrderValue', {
  uses: { revenue, orderCount },
  formula: ({ revenue, orderCount }) =>
    divide(revenue, nullIfZero(orderCount)),
  label: 'Average Order Value',
  description: 'Revenue divided by order count.',
});

On this page