Skip to content
DataHashi Docs

Semantic model glossary

This is the vocabulary every datahashi model, query, and error message uses. Precise terms make precise queries — an LLM agent grounds itself in exactly this vocabulary before it ever queries.

New here? Skim the diagram below for the overall shape, then read The vocabulary of a model top to bottom once — each term builds on the last, and the worked example at the bottom ties them together with a real question.

Vocabulary hierarchy: entities, dimensions, measures, and metrics Entities customer and order connect through the order_customer relationship. Each entity has dimensions and measures attached; a metric like avg_order_value is built on top of a measure. A governed credential sees metrics only; an explore credential additionally sees measures and dimensions. avg_order_value (metric) revenue ÷ order_count region dimension lifetime_value measure status dimension revenue measure customer order order_customer Governed — sees metrics only Explore — + measures & dimensions
A metric is built on measures; measures and dimensions attach to entities; entities connect through the join graph.

These six terms describe the model itself — the shape you define once, in YAML, independent of any particular query. See Write your first model for these applied to a real example.

The layered set of definitions that map your physical data to business vocabulary: entities, dimensions, measures, metrics, segments, and views — independent of which warehouse dialect backs it. A workspace may hold several models; each one binds to exactly one connected source.

A business noun with a primary key and relationships to other entities — customer, order. Backed by a physical table, or by a curated SELECT when the raw table doesn’t map cleanly onto one business noun.

An attribute of an entity used to slice or group results — region, status, order_date. A temporal dimension declares which grains (day, week, month, quarter, year, hour, minute) it can be bucketed at.

A raw aggregatable field on one entity, with a single aggregation: sum, count, count_distinct, min, max, or count_distinct_approx. Measures are the reusable primitive — revenue (sum(amount)), order_count (count(id)). There is deliberately no avg aggregation; averages are metrics, computed after aggregation, never row-wise.

A named, governed expression built on one or more measures — a ratio or arithmetic formula, computed after aggregation. avg_order_value = revenue / order_count is a metric, not a measure: avg(amount) would weight a customer’s orders wrong once you join across a fan-out relationship. Metrics are what a governed credential is allowed to select; measures are not.

The graph of entities connected by named relationships (with cardinality and key columns). The compiler walks this graph to resolve join paths between the measures and dimensions a query selects — you name what you want; you never write the join yourself. Relationship names are unique across the whole model, so role-playing edges (bill_to vs. ship_to on the same pair of entities) can be selected unambiguously.

These describe what a consumer sends at query time — and who’s allowed to ask for what.

The structured request every consumer sends — REST or MCP — and the only thing that gets compiled into SQL. It names one semantic model, and some combination of metrics/measures, dimensions (with an optional grain), filters, segments, a view, ordering, and a row limit. It is never SQL, and never a raw table or column name. See Query the API for the full shape.

A named, reusable filter fragment defined on the model — “completed orders only” — that a query references by name instead of repeating the same filter everywhere.

A named, curated projection of one model’s exposed surface: a subset of its metrics, dimensions, and (in explore mode) measures. A view can only narrow what a consumer may reference — never widen it. Row-level security and mode gating still apply after a view is applied.

Two access surfaces over the same compiler, selected by the credential — never by the query itself:

  • Governed exposes named metrics (and views over them) only.
  • Explore additionally exposes raw measures and dimensions across the join graph, for internal tooling and analysts.

A materialized pre-aggregation: measures pre-aggregated over chosen dimensions at a grain, stored so the hot query path reads an answer instead of recomputing it against the warehouse. Rollups are data, not something you query directly — the engine decides when a rollup covers a query and routes to it transparently.

Two ways the same query gets answered A semantic query that isn't covered by any rollup computes live against the warehouse. Once a matching rollup exists, the identical query is served from it instead — same request, same response shape, only latency differs. Semantic query same request either way Warehouse aggregates now slower — live compute Rollup already pre-aggregated faster — cache hit Response same columns & rows shape
Whether an answer came from a rollup or live from the warehouse is never reported back — only latency tells the difference.
  • A workspace (called an “org” in the API) is your account’s isolation boundary — it owns sources, models, rollups, and API keys.
  • A source is a physical warehouse the workspace has access to (Snowflake, BigQuery, Postgres, MySQL, DuckDB). A workspace may have several; each semantic model binds to exactly one.
  • A connection is the address and credential that reaches a source. Rotating a connection re-addresses the same source without renaming it, and is never something a query selects directly — the source is always derived from the model you’re querying.

“Is average order value a measure?”

No — sum(amount) and order_count are measures. Average order value is a metric: a ratio of those two, computed after aggregation, not avg(amount) row-wise.

“And if I want it by region — region lives on the customer, not the order?”

Right. The compiler walks the join graph from order to customer to reach region. You list region in the semantic query; you never write the join.