Overview
Custom models use Apache Ossie, an open YAML format for semantic models. Interact reads Ossie version0.2.0.dev0 and adds a few optional settings of its own through custom_extensions.
Each file:
- ends in
.ossie.yamlor.ossie.yml - lives under the Model path of your custom semantic layer
- holds one model with at least one dataset
Full example
Two datasets, a relationship between them, and three metrics.orders.ossie.yaml
orders.revenue and orders.average_order_value by stores.store_city per month joins fact_orders to dim_store on store_id, and computes the average order value from the summed revenue and order count, not as an average of averages.
Model
The top level of a file.Datasets
A dataset is one table, or oneSELECT, that you can query.
Interact checks plain table references against the warehouse and flags fields whose column doesn’t exist. Datasets with a
SELECT as source are not checked.
Limit a SELECT to the date range
ASELECT source can contain a {DATE_FILTER(column)} token. Interact replaces it with a filter on the query’s date range, so the warehouse scans only the dates it needs. Point the dataset at a time field with the date_filter_field extension:
A query without a date range replaces the token with
TRUE. The date_filter_field must be a time field of the dataset.
The filter compares the column with TIMESTAMP values. When the column is a DATETIME or DATE, set the date_filter_datatype extension to DateTime or Date, and Interact converts the date range to that type (in UTC):
Fields
Fields are the dimensions of a dataset: what you group and filter by.
Time dimensions can be grouped by day, week, month and so on, in the timezone set in Data mapping.
Set
datatype to the type the expression returns, not the type of the underlying column:
So
TIMESTAMP(orders.order_date) is DateTimeTz, even though order_date is a DATE column.
A field can stand in for a field of another dataset with the conforms_to extension. See Metrics from several datasets.
Metrics
Metrics are the numbers you calculate: sums, counts, ratios.Which dataset a metric belongs to
Interact links a metric to the dataset its expression uses, for exampleorders in SUM(orders.revenue_inc_vat). When the expression uses more than one dataset, or none, set the dataset with the dataset extension. Sync fails with set custom_extensions TURNTWO "dataset" when it cannot tell.
How a metric aggregates
Interact reads the aggregation from the expression:
Set the
agg extension to override it.
A derived metric either refers to other metrics or aggregates columns itself, not both:
{orders.revenue} / {orders.order_count}refers to metrics. Interact computes each one and divides the results.SUM(orders.revenue_inc_vat) / COUNT(orders.order_id)aggregates columns. Interact treats it like any other aggregate on its dataset.{orders.revenue} / COUNT(orders.order_id)mixes both, and sync rejects it. Make the count a metric of its own and refer to it.
Metrics from several datasets
A query can combine metrics from different datasets, such as leads fromleads and purchased matches from lead_matches. Interact aggregates each dataset on its own rows and then combines the results on the query’s dimensions. A ratio across two datasets is therefore not inflated by a join that repeats rows.
For this to work, each dimension and filter in the query must be available to each metric’s dataset, in one of three ways:
- the metric’s dataset can reach the dimension’s dataset through relationships
- the metric’s dataset has a time field with the same name, for a time dimension
- the metric’s dataset has a field with the
conforms_toextension pointing at the dimension
Expressions
Fields and metrics have anexpression with one or more SQL dialects:
BIGQUERY when present, then ANSI_SQL, then the first one listed.
- A plain column name in a field or metric, such as
order_id, refers to that column in the dataset’s own source. Interact adds the dataset name (orders.order_id), so a column with the same name in a joined dataset doesn’t clash. dataset.column, such asorders.price_inc_vat, refers to a column in a metric expression.{dataset.member}refers to another field or metric, such as{orders.revenue}. Use this for ratios, so Interact can combine the underlying aggregates correctly.{member}refers to a member of the same dataset.
Relationships
Relationships let a query combine datasets. Each relationship is many-to-one:from is the detailed dataset (many rows), to is the dataset it looks up (one row per key).
Interact joins with a
LEFT JOIN from the dataset that can reach every other dataset in the query, along the shortest chain of relationships. If no such dataset exists, the query fails with no relationship path connects these datasets.
When two chains are equally short, for example lead_matches → brands directly and via categories, mark the intended relationship with the preferred extension. Sync reports remaining ties as X reaches Y over N equally short join paths.
to: interact_products.
Use the extra_condition extension to add a condition to the join, such as matching on label as well:
AI context
ai_context gives agents extra guidance. It can be a string, or an object:
instructions and synonyms are given to agents. On fields and metrics, ai_context is only used when description is empty.
Interact extensions
Interact-specific settings go incustom_extensions with vendor_name: TURNTWO. data is a JSON string:
data is not valid JSON, or has a value Interact doesn’t accept, is skipped on sync.
On a dataset
On a field
On a metric
On a relationship
Checks on sync
When you sync, Interact checks every file and the combined model. A file is skipped when:- it is not valid YAML, or misses a required key
- a
TURNTWOextension is not valid JSON or has an unknown value - a metric’s dataset cannot be determined, or points to a dataset that doesn’t exist
- duplicate dataset names, and duplicate field or metric names within a dataset
primary_keycolumns that aren’t fields{DATE_FILTER(...)}tokens without a timedate_filter_fieldconforms_tovalues that aren’t fields- derived metrics that both refer to metrics and aggregate columns
- datasets that reach another dataset over equally short join paths without a
preferredrelationship