Skip to content

Schema structure

A complete example

Here is a small but complete Mondrian-4 schema — one cube, one dimension, two measures. Saiku accepts schemas in either YAML (the default) or XML; pick a format below and every example on the site switches to match.

schema:
name: "Sales Example"
metamodel_version: "4.0"
physical_schema:
tables:
- name: "sales_fact"
schema: "demo"
key:
- "sale_id"
- name: "dim_customer"
schema: "demo"
shared_dimensions:
Customer:
table: "dim_customer"
key: "Customer"
attributes:
- name: "Customer"
key:
- "customer_id"
name_column: "customer_name"
- name: "Gender"
key:
- "gender"
has_hierarchy: false
hierarchies:
- name: "Customers"
levels:
- "Gender"
- "Customer"
cubes:
Sales:
dimensions:
- source: "Customer"
measure_groups:
- name: "Sales"
table: "sales_fact"
measures:
- name: "Unit Sales"
column: "units"
aggregator: "sum"
format_string: "#,###"
- name: "Revenue"
column: "revenue"
aggregator: "sum"
format_string: "#,##0.00"
dimension_links:
- type: "foreign_key"
dimension: "Customer"
foreign_key_column: "customer_id"

Structure of a schema

The overall structure of a Mondrian-4 schema XML document looks like this:

<Schema>
<PhysicalSchema>
<Table>
<Key>
<Column/>
</Key>
</Table>
<Query>
<SQL/>
</Query>
<InlineTable>
<ColumnDefs>
<ColumnDef/>
</ColumnDefs>
<Key/> <!-- same structure as Table/Key -->
<Rows>
<Row>
<Value/>
</Row>
</Rows>
</InlineTable>
<Link/>
</PhysicalSchema>
<Dimension/> <!-- shared; same structure as Dimension within a Cube -->
<Cube>
<Dimensions>
<Dimension>
<Attributes>
<Attribute>
<Key>
<Column/>
</Key>
<Name/> <!-- same structure as Key -->
<Caption/> <!-- same structure as Key -->
<OrderBy/> <!-- same structure as Key -->
<Closure/>
<MemberFormatter>
<Script/>
</MemberFormatter>
<Property>
<PropertyFormatter>
<Script/>
</PropertyFormatter>
</Property>
</Attribute>
</Attributes>
<Hierarchies>
<Hierarchy>
<Levels>
<Level/>
</Levels>
</Hierarchy>
</Hierarchies>
</Dimension>
</Dimensions>
<MeasureGroups>
<MeasureGroup>
<Measures>
<Measure/>
<MeasureRef/>
</Measures>
<DimensionLinks>
<ForeignKeyLink/>
<FactLink/>
<ReferenceLink/>
<CopyLink/>
<NoLink/>
</DimensionLinks>
</MeasureGroup>
</MeasureGroups>
<CalculatedMembers>
<CalculatedMember>
<Formula/>
<CalculatedMemberProperty/>
<CellFormatter>
<Script/>
</CellFormatter>
</CalculatedMember>
</CalculatedMembers>
<NamedSets>
<NamedSet>
<Formula/>
</NamedSet>
</NamedSets>
</Cube>
<Role>
<SchemaGrant>
<CubeGrant>
<DimensionGrant/>
<HierarchyGrant>
<MemberGrant/>
</HierarchyGrant>
</CubeGrant>
</SchemaGrant>
<Union>
<RoleUsage/>
</Union>
</Role>
<UserDefinedFunction>
<Script/>
</UserDefinedFunction>
<Parameter/>
</Schema>

Element order is not significant. For example, a <UserDefinedFunction> element may appear before one <Cube> and after another — Mondrian-4 parses the document positionally but treats element order as advisory. This is a significant change from Mondrian 3.x, where element order was strictly required.

The content of each element is described in the following pages of this section and in the YAML schema reference.

The Schema element

<Schema> is the root element of every Mondrian schema. A minimal example:

schema:
name: "Rock Sales"
metamodel_version: "4.0"

Required and common attributes

AttributeRequiredDefaultDescription
nameyesDisplay name for this schema
metamodelVersionnoauto-detectedSchema format version. Use "4.0" for all new schemas
captionnoOverride the display name seen by client tools
descriptionnoHuman-readable description
measuresCaptionnoCaption for the virtual [Measures] dimension
defaultRolenoRole applied when no role is specified by the connection
quoteSqlnotrueWhether Mondrian quotes SQL identifiers
missingLinknowarningBehaviour when a dimension link is missing — warning, error, or ignore
localesnoComma-separated list of locale codes for localised captions

The metamodelVersion attribute tells Mondrian which version the schema was written for. If you omit it, Mondrian infers the version from the schema contents. For all new schemas set it to "4.0".

Annotations

The major element types — schema, cube, shared dimension, dimension, attribute, hierarchy, level, measure group, measure, calculated member — all support annotations. An annotation lets you attach arbitrary key/value metadata to any schema element, which is particularly useful for tools that need to store information without modifying the official Mondrian schema definition.

Add an <Annotations> element as a child of the element you want to annotate, then include one or more <Annotation> elements inside it. Annotation name values must be unique within their parent element. If you are creating annotations for a specific tool, choose names carefully to avoid clashes with other tools.

schema:
name: "Rock Sales"
metamodel_version: "4.0"
annotations:
Author: "Fred Flintstone"
Date: "10,000 BC"
cubes:
Sales:
...

Conventional annotation names

Some annotation names are used by convention across tools:

AnnotationElement(s)Description
AnalyzerBusinessGroupLevelCreates folders in the UI
AnalyzerBusinessGroupDescriptionLevelDescription for those folders
AnalyzerDateFormatLevelUsed for relative date filters
AnalyzerHideInUIMeasure, CalculatedMemberHides the field from the UI
AnalyzerDisableDrillLinksCubeDisables drillthrough links on the cube

Locale-aware tools use dot-qualified names by convention — for example caption.de_DE for a German caption, description.fr_FR for a French description. The FoodMart demo schema shows this pattern on the Sales cube:

annotations:
caption.de_DE: "Verkaufen"
caption.fr_FR: "Ventes"
description.fr_FR: "Cube des ventes"

The logical model

The most important components of a schema are cubes, measures, attributes, and dimensions:

  • A cube is a data set describing one or more business processes over a particular time period.
  • A fact is the data representing one occurrence of a process — for example, a line item describing the sale of a product to a customer, or a pay period for an employee.
  • A measure is a quantity you want to aggregate within a cube — for example, unit sales of a product, or an employee’s salary.
  • An attribute is a value, possessed by every fact, by which you can divide facts into subsets. You might slice product sales by colour, customer gender, and the store where the product was sold; colour, gender, and store are all attributes.
  • A dimension is a grouping of related attributes. For example, name, gender, zip code, and eye colour are attributes of a Customer dimension; colour, weight, and manufacturer are attributes of a Product dimension.

Here is a complete, working example of a simple schema that ties these concepts together:

schema:
name: "Sales"
metamodel_version: "4.0"
physical_schema:
tables:
- name: "sales_fact_1997"
- name: "customer"
- name: "time_by_day"
cubes:
Sales:
dimensions:
- name: "Customer"
table: "customer"
key: "Id"
attributes:
- name: "Gender"
- name: "Id"
- name: "Time"
table: "time_by_day"
key: "Day"
attributes:
- name: "Year"
- name: "Quarter"
key:
- "the_year"
- "quarter"
- name: "Month"
key:
- "the_year"
- "month_of_year"
- name: "Day"
hierarchies:
- name: "Yearly"
has_all: false
levels:
- "Year"
- "Quarter"
- "Month"
measure_groups:
- name: "Sales"
table: "sales_fact_1997"
measures:
- name: "Unit Sales"
column: "unit_sales"
aggregator: "sum"
format_string: "#,###"
- name: "Store Sales"
column: "store_sales"
aggregator: "sum"
format_string: "#,###.##"
- name: "Store Cost"
column: "store_cost"
aggregator: "sum"
format_string: "#,###.00"
dimension_links:
- type: "foreign_key"
dimension: "Customer"
foreign_key_column: "customer_id"
- type: "foreign_key"
dimension: "Time"
foreign_key_column: "time_id"
calculated_members:
- name: "Profit"
dimension: "Measures"
formula: "[Measures].[Store Sales] - [Measures].[Store Cost]"
properties:
- name: "FORMAT_STRING"
value: "$#,##0.00"

This schema contains a single cube called “Sales” with two dimensions (“Customer” and “Time”), three base measures, and one calculated member (“Profit”). You can write an MDX query against it immediately:

SELECT {[Measures].[Unit Sales], [Measures].[Store Sales]} ON COLUMNS,
{Descendants([Time].[Yearly].[1997].[Q1])} ON ROWS
FROM [Sales]
WHERE [Customer].[Gender].[F]

Which produces results like:

[Time][Measures].[Unit Sales][Measures].[Store Sales]
[1997].[Q1]32,910$69,798.23
[1997].[Q1].[Jan]10,932$23,309.04
[1997].[Q1].[Feb]10,266$21,773.93
[1997].[Q1].[Mar]11,712$24,715.26

The sections that follow explain each part of this schema in detail.


Content adapted from the Mondrian project schema guide, available under the Eclipse Public License v1.0 (http://www.eclipse.org/legal/epl-v10.html).