Pular para o conteúdo

Exportando para Apache Ossie

Apache Ossie (antigo Open Semantic Interchange) é um projeto Apache em incubação que define uma especificação YAML/JSON portável para troca de modelos semânticos entre ferramentas de analytics, AI e BI. O Saiku distribui um exportador que lê qualquer schema Mondrian e produz um documento Ossie válido — as mesmas definições de measure e dimension tornam-se consumíveis por dbt, GoodData, Snowflake, Databricks, Salesforce e toda outra ferramenta com um conversor Ossie.

Início rápido

Passe um schema XML Mondrian, obtenha YAML Ossie de saída:

Terminal window
java -jar saiku-launcher/target/saiku-4.6.0.jar ossie-export \
--in saiku-home/data/Pharma.xml \
--out pharma.ossie.yaml

Ou use stdin/stdout para scripting:

Terminal window
cat schema.xml | saiku ossie-export > schema.ossie.yaml

O comando sai com código não-zero se o input não pode ser lido (exit 2) ou o output não pode ser escrito (exit 3), com uma linha de diagnóstico em stderr. Runs bem-sucedidos reportam quantos modelos semânticos foram escritos e (se algum) quais cubos foram pulados:

ossie-export: wrote 1 semantic model(s) to pharma.ossie.yaml

O que mapeia para o quê

O exportador segue esta tabela de mapeamento 1:1. Tudo exceto exceções explicitamente listadas cai na coluna alvo verbatim.

Elemento MondrianSaída Ossie
<Cube>Uma entrada semantic_model
Fact <Table name="..." schema="..."/> do cuboPrimeiro dataset, source: "<schema>.<table>"
<Dimension foreignKey="..."> com <Hierarchy><Table/>Um dataset de dim por hierarquia, mais um relationship de fact.foreignKey → dim.primaryKey
<Level name="..." column="..."/>Um field na dim (ou fact, para dims degeneradas), com expression.dialects[0]=ANSI_SQL:column
<Level ... levelType="TimeYears"> (ou Quarters/Months/Days)Field ganha dimension.is_time: true
<Measure name="..." column="..." aggregator="sum"/>Uma metric com ambos os dialetos ANSI_SQL (SUM(fact.column)) e MDX ([Measures].[Name])
<Measure aggregator="distinct-count">ANSI_SQL: COUNT(DISTINCT fact.column) — mais count, min, max, avg todos traduzem
<CalculatedMember><Formula>...</Formula></CalculatedMember>Metric com expressão só-MDX (sem tradução ANSI SQL confiável para fórmulas MDX)
<Annotation name="saiku.semantic.description">ai_context.instructions do elemento
<Annotation name="saiku.semantic.synonyms">ai_context.synonyms[] do elemento (split por CSV, aparado)
<Annotation name="saiku.semantic.pii">truecustom_extensions: [{vendor_name: SAIKU, data: '{"pii":true}'}] — booleano JSON, não string
<Annotation name="saiku.semantic.{cardinality,grain,aggregation_kind,required_filters}">Mesma extensão de fornecedor SAIKU, valores serializados como strings JSON

Exemplo trabalhado — cubo Pharma

Trecho de input de saiku-home/data/Pharma.xml:

<Cube name="Pharma Rx">
<Table name="fact_pharma" schema="public"/>
<Dimension name="Prescriber" foreignKey="prescriberkey">
<Hierarchy hasAll="true" primaryKey="prescriberkey">
<Table name="dim_prescriber" schema="public"/>
<Level name="Prescriber" column="prescriberkey" nameColumn="prescribername"
type="Numeric" uniqueMembers="true">
<Annotations>
<Annotation name="saiku.semantic.pii">true</Annotation>
</Annotations>
</Level>
</Hierarchy>
</Dimension>
<Measure name="Quantity" column="quantity_units" aggregator="sum" formatString="#,##0"/>
</Cube>

Produz este fragmento Ossie:

version: 0.2.0.dev0
semantic_model:
- name: Pharma Rx
datasets:
- name: fact_pharma
source: public.fact_pharma
description: Fact table for cube 'Pharma Rx'.
- name: Prescriber
source: public.dim_prescriber
primary_key:
- prescriberkey
fields:
- name: Prescriber
expression:
dialects:
- dialect: ANSI_SQL
expression: prescriberkey
custom_extensions:
- vendor_name: SAIKU
data: "{\"pii\":true}"
relationships:
- name: fact_pharma_to_Prescriber
from: fact_pharma
to: Prescriber
from_columns:
- prescriberkey
to_columns:
- prescriberkey
metrics:
- name: Quantity
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(fact_pharma.quantity_units)
- dialect: MDX
expression: "[Measures].[Quantity]"

O que (ainda) não é suportado

O conversor de primeira geração trata o formato híbrido clássico Mondrian 3–4 usado por Pharma, Bank e a maioria dos schemas de clientes. Ele ainda não trata:

  • Formato wrapper <MeasureGroups> / <Dimensions> do Mondrian 4. FoodMart usa isso. Cubos com este formato são pulados (reportado em stderr) em vez de emitidos como stubs schema-inválidos. Trabalho de follow-up rastreado no épico pai Ossie/SQL.
  • Cubos virtuais (<VirtualCube>) — incluindo nosso exemplo Warehouse-and-Sales. Pulados como acima.
  • Hierarquias parent-child. Emitidas como levels planos; a relação hierárquica não é representável no formato atual orientado a dataset do Ossie (o grupo de trabalho de hierarquia do Ossie está em andamento — veja o roadmap do Ossie).
  • Shared dimensions consumidas via <DimensionUsage source=...>. Só o embedding clássico por-cubo <Dimension> funciona hoje.

Quando a história de hierarquia do Ossie estabilizar (alvo: v0.3.0+) e o conversor de MG Mondrian-4 do Saiku chegar, esta tabela vai encolher.

Consumindo a saída

O YAML Ossie é verificado por validação contra o osi-schema.json do apache/ossie — todo arquivo que o exportador produz faz round-trip pelo schema com zero achados (há um teste de unidade que assevera isso em cada commit). Consumidores downstream:

  • dbt — os conversores de referência do Ossie incluem um módulo dbt.
  • Snowflake, Salesforce, GoodData, Polaris, Databricks — mesmo diretório.
  • Apache Superset e Metabase — sem conversor de primeira parte ainda no momento da escrita, mas o trabalho de SQL-sobre-Ossie no roadmap do Saiku (épico pai saiku#1387) fará o próprio Saiku consultável como uma camada semântica via SQL.

Relacionado