datachile / datachile-mondrian

Schema de Mondrian para DataChile. Server API.
https://chilecube.datachile.io/cubes
1 stars 2 forks source link

Datachile Mondrian

Build Status

Es la implementación de la capa lógica usando Mondrian REST para Datachile.

Contiene la configuración del esquema de cubos y provee el entrypoint REST de la API para consultas.

Documentación completa para crear un schema aquí: Mondrian Schema

Para desarrollo local

  1. Instalar JRuby. Usar RVM es recomendado.
  2. rvm install "jruby-9.2.5.0"
  3. Instalar dependencias con bundle install
  4. Ejecutar jruby -G -S jbundle install
  5. Ejecutar jruby -S gem install jbundler
  6. Duplicar config.yaml.example bajo el nombre config.yaml y completar los datos.
  7. Correr server JRUBY_OPTS=-G MONDRIAN_REST_CONF=pwd/config.yaml MONDRIAN_REST_SECRET=lala JAVA_OPTS="-Dlog4j.configuration=file:log4j.properties -Dmondrian.olap.SsasCompatibleNaming=true" rackup

Para concatenar fragmentos

  1. Instalar mondrian-schema-cat
  2. Ejecutar moncat -d frags/ -o schema.xml

Para crear archivo de ejecución

Ejecutar los comandos anteriormente descritos puede resultar una labor tediosa cada vez que se realicen modificaciones en frags, teniendo que reiniciar el servidor. Se sugiere crear un archivo de script, que permita tener todos los comandos necesarios para iniciar el servidor.

  1. Crear el archivo init.sh, y agregar los comandos necesarios para inicializar (como sugerencia, primero moncat y luego rackup)
  2. Ejecutar chmod +x init.sh
  3. Ejecutar ./init.sh

Luego de estas etapas, a futuro sólo basta ejecutando ./init.sh.

Conceptos básicos

Descripción y ejemplos de las palabras clave en Mondrian y OLAP.

Ejemplo de cubo

En el siguiente diagrama se puede apreciar un ejemplo de cubo en donde existen 3 dimensiones:

CUBO OLAP

En la intersección de los ejes -cubos celestes- está la measure agregada y el valor definido que estamos buscando en este query.

Tablas fact_ y tablas dim_

El diagrama de estrella para una base de datos relacional organiza la información pensando en que:

Dimensiones en tablas vs Dimensiones inline

Las dimensiones puede ser definidas en una tabla y mapear los campos que respondan a los ids y los nombres, por ejemplo la dimensión Geography:

<Dimension name="Geography">
  <Annotations>
    <Annotation name="index_as">geo</Annotation>
  </Annotations>

  <Hierarchy hasAll="true" primaryKey="id">
    <Table name="dim_comunas" schema="public"/>

    <Level column="region_id" name="Region" nameColumn="region_name" uniqueMembers="true"/>

    <Level column="comuna_datachile_id" name="Comuna" nameColumn="comuna_name" uniqueMembers="true"/>
  </Hierarchy>
</Dimension>

... o bien -sin son pequeñas- pueden ser definidas como tablas inline como por ejemplo la dimensión Sex:

<Dimension name="Sex">
  <Annotations>
    <Annotation name="es_element_caption">Sexo</Annotation>
  </Annotations>

  <Hierarchy hasAll="true" primaryKey="sex_id">
    <InlineTable alias="dim_sex">
      <ColumnDefs>
        <ColumnDef name="sex_id" type="Numeric"/>
        <ColumnDef name="description" type="String"/>
        <ColumnDef name="es_description" type="String"/>
      </ColumnDefs>
      <Rows>
        <Row>
          <Value column="sex_id">0</Value>
          <Value column="description">No data</Value>
          <Value column="es_description">No informa</Value>
        </Row>
        <Row>
          <Value column="sex_id">2</Value>
          <Value column="description">Male</Value>
          <Value column="es_description">Masculino</Value>
        </Row>
        <Row>
          <Value column="sex_id">1</Value>
          <Value column="description">Female</Value>
          <Value column="es_description">Femenino</Value>
        </Row>
      </Rows>
    </InlineTable>

    <Level column="sex_id" name="Sex" nameColumn="description" uniqueMembers="true" caption="Sex">
      <Annotations>
        <Annotation name="es_caption">Description ES</Annotation>
        <Annotation name="es_element_caption">Sexo</Annotation>
      </Annotations>

      <Property column="es_description" name="Description ES"/>
    </Level>
  </Hierarchy>
</Dimension>

En general la decisión estará basada en la cantidad de members que tenga esa dimensión.

i18n

Repetir datos puede ser un detalle sin importancia en las tablas dim_ dado que OLAP siempre hará agregaciones. Pero puede multiplicarse si se necesita multilenguaje. Es la única manera de hacerlo: tener las dimensiones -y sus niveles- en varios idiomas en campos separados. Se indica el campo dentro de cada Level utilizando Annotations y Property.

Ejemplo de Dimension inline sobre grados de discapacidad:

<Dimension foreignKey="disability_grade" name="Disability Grade">
  <Annotations>
    <Annotation name="es_element_caption">Grado de discapacidad</Annotation>
  </Annotations>

  <Hierarchy hasAll="true">
    <InlineTable alias="disability_grade">
      <ColumnDefs>
        <ColumnDef name="id" type="Numeric"/>
        <ColumnDef name="description" type="String"/>
        <ColumnDef name="es_description" type="String"/>
      </ColumnDefs>
      <Rows>
        <Row>
          <Value column="id">1</Value>
          <Value column="description">No disability</Value>
          <Value column="es_description">Sin discapacidad</Value>
        </Row>
        <Row>
          <Value column="id">2</Value>
          <Value column="description">Slight to moderate</Value>
          <Value column="es_description">Leve a moderada</Value>
        </Row>
        <Row>
          <Value column="id">3</Value>
          <Value column="description">Severe</Value>
          <Value column="es_description">Severa</Value>
        </Row>
      </Rows>
    </InlineTable>

    <Level column="id" name="Disability Grade" nameColumn="description" uniqueMembers="true">
      <Annotations>
        <Annotation name="es_caption">Description ES</Annotation>
      </Annotations>

      <Property column="es_description" name="Description ES"/>
    </Level>
  </Hierarchy>
</Dimension>

Luego en el query habrá que solicitar el caption al drilldown basado en el nombre de la property.

LLamadas a la API

Otros conceptos necesarios para comprender la manera de realizar queries:

# Dimensiones solicitadas por las cuales combinar miembros y agregar:
drilldown[]: [Origin Country].[Country].[Country]
drilldown[]: [Geography].[Geography].[Comuna]
drilldown[]: [Date].[Date].[Year]

# Medida de la cual deseo agregación
measures[]: CIF US

# Cortes a los datos por determinados años. (opcional)
cut[]: {[Date].[Date].[Year].&[2013], [Date].[Date].[Year].&[2014], [Date].[Date].[Year].&[2015]}

# Agrego otro corte, sólo para la región 1
cut[]: [Geography].[Geography].[Region].&[1]}

Para más detalle de la manera de realizar queries: Mondrian REST.

Links y repositorios relacionados sobre Mondrian

Repositorios relacionados sobre DataChile