docs-mintlify/recipes/data-modeling/style-guide.mdx
While Cube allows for certain flexibility with regards to data modeling, following this fairly opinionated style guide helps create maintainable semantic layers and reduce effort to support them in the long run.
This style guide is intended to be used by:
model/cubes and
model/views folders.cube_project
└── model
├── cubes
│ ├── finance
│ │ ├── stripe_invoices.yml
│ │ └── stripe_payments.yml
│ └── sales
│ └── base_opportunities.yml
└── views
├── product
│ └── cloud_tenants.yml
└── sales
└── opportunities.yml
public: false for all cubes.
Only views can be exposed to visualization tools.base_ prefix to the cube's name,
e.g., base_opportunities.yml.sql_table instead of sql, i.e., use
sql_table: schema.table instead of sql: SELECT * FROM schema.table.many_to_one, one_to_many, one_to_one join relationship
types instead of belongs_to, has_many, has_one.namesql_aliasextendsdata_sourcesqlsql_tabletitledescriptionpublicrefresh_keymetapre_aggregationsjoinsdimensionshierarchiessegmentsmeasuresaccess_policynametitledescriptionsqltypeprimary_keysub_querypublicformatfiltersdrill_memberstitle and description if the name is not intuitive.cubes:
- name: line_items
sql_table: public.line_items
public: false
joins:
- name: products
sql: "{CUBE}.product_id = {products.id}"
relationship: many_to_one
- name: orders
sql: "{CUBE}.order_id = {orders.id}"
relationship: many_to_one
dimensions:
- name: id
sql: id
type: number
primary_key: true
- name: created_date
sql: created_at
type: time
measures:
- name: count
type: count
- name: total_amount
sql: price
type: sum
namedescriptionpubliccubesfoldersaccess_policyviews:
- name: orders
cubes:
- join_path: base_orders
includes:
# dimensions
- status
- created_date
# measures
- total_amount
- total_amlunt_shipped
- count
- average_order_value
- join_path: base_orders.line_items.products
includes:
- name: name
alias: product
- join_path: base_orders.line_items.products.product_categories
includes:
- name: name
alias: product_category
- join_path: base_orders.users
prefix: true
includes:
- city
!= instead of <>.AS keyword when aliasing columns, expressions, and tables.SELECT), put it on the same line as the opening keyword.cubes:
- name: california_users
sql: |
SELECT
id,
first_name,
last_name
FROM public.users WHERE state = 'CA'
dimensions:
- name: id
sql: id
type: number
primary_key: true
- name: first_name
sql: first_name
type: string
- name: last_name
sql: last_name
type: string
measures:
- name: count
type: count
.yml extension instead of .yaml.|) for multi-line strings
over folded style (>).cubes:
- name: users
description: |
All users in the system.
Note that this dataset contains PII data.
sql_table: public.users
dimensions:
- name: id
sql: id
type: number
primary_key: true
- name: city
sql: city
type: string
- name: lifetime_value
sql: "{line_items.total_amount}"
type: number
sub_query: true
measures:
- name: count
type: count
- name: total_orders_amount
sql: "{lifetime_value}"
type: sum
cube(`users`, {
sql_table: `public.users`,
dimensions: {
id: {
sql: `id`,
type: `number`,
primary_key: true
},
city: {
sql: `city`,
type: `string`
},
lifetime_value: {
sql: `${line_items.total_amount}`,
type: `number`,
sub_query: true
}
},
measures: {
count: {
type: `count`
},
total_orders_amount: {
sql: `${lifetime_value}`,
type: `sum`
}
}
})
This style guide was inspired in part by: