Better models doc#138
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughRewrites and reorganizes ChangesModels concept documentation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| # Models | ||
|
|
||
| A model maps a database table (or SQL subquery) to queryable **columns** and **measures**. Models are defined as YAML files or created via the API/MCP. | ||
| A model is SLayer's view of a database table. It declares the columns, named metric formulas, joins, and always-applied filters that queries can build on. Models are defined as YAML (one file per model under `models/<data_source>/`) or created via API/MCP — the two paths produce the same persisted object. |
There was a problem hiding this comment.
Worth mentioning that this could also be based on a sql query
| filter: "status = 'completed'" | ||
| ``` | ||
|
|
||
| `active_revenue:sum` then generates `SUM(CASE WHEN status = 'active' THEN amount END)`. The filter does nothing when the column is used as a group-by dimension — it fires only inside aggregations. |
There was a problem hiding this comment.
Is that true? I don't think we want it to be have like that, no?
For me, a filter is just syntactic sugar for case when
There was a problem hiding this comment.
Yes, when a Column.filter column is used as a dimension, the filter is silently dropped. EnrichedDimension doesn't even carry a filter_sql field (see slayer/engine/enriched.py:31), so by construction it can't propagate. The dimension build path (generator.py:1313) just resolves dim.sql raw.
Dry-run proof:
-- Model: column `active_status` has sql=status, filter="status = 'active'"
-- Query: dimensions=["active_status"]
SELECT
orders.status AS "orders.active_status"
FROM orders AS orders
GROUP BY
orders.statusNo CASE WHEN, no WHERE. Every status value shows up.
If you want, we can change that behaviour, but let's make it in a separate PR as I now just wanna quickly update the doc.
| | `string` | count, count_distinct, first, last, min, max | | ||
| | `boolean` | count, count_distinct, sum, min, max, first, last | | ||
| | `date` / `time` | count, count_distinct, first, last, min, max | | ||
| Bare column names (`"amount"`) auto-qualify against the model's table at query time. For cross-column arithmetic in the same model, prefix with the model name: `"orders.amount * orders.quantity"`. For joined columns inside a model's own `sql`, use the `__` alias form (`customers__regions.name`) — see [Joins](#joins). |
There was a problem hiding this comment.
This is not necessary, source model is assumed
|



Less text yet more helpful details
Summary by CodeRabbit