Code Monkey home page Code Monkey logo

mondrian_demo's Introduction

Overview

This is sample Rails application that demonstrates usage of mondrian-olap gem. It was used during RailsWayCon 2011 conference presentation Multidimensional Data Analysis with JRuby.

Preparation

Create mysql database "foodmart" and import sample data with e.g.

mysqladmin -u root -p create foodmart
mysql -u root -p -D foodmart < db/foodmart.sql

Create user "foodmart"

mysql -u root -p
mysql> grant all on foodmart.* to 'foodmart'@'localhost' identified by 'foodmart';

Install JRuby (e.g. with rvm).

Install all necessary gems with bundle install.

Run application with

jruby -S script/rails server

or if you would like to see debugging output from Mondrian (including generated SQL statements) then start application with

jruby -J-Dlog4j.configuration=config/log4j.properties -S script/rails s

MDX demo

Go to http://localhost:3000/mdx and input

SELECT  {[Measures].[Unit Sales], [Measures].[Store Sales]} ON COLUMNS,
        {[Products].children} ON ROWS
  FROM  [Sales]
  WHERE ([Time].[1997].[Q1], [Customers].[USA].[CA])

It generates SQL similar to this:

select "CUSTOMER"."STATE_PROVINCE" as "c0", "PRODUCT_CLASS"."PRODUCT_FAMILY" as "c1", "TIME_BY_DAY"."THE_YEAR" as "c2", "TIME_BY_DAY"."QUARTER" as "c3", sum("SALES_FACT_1997"."UNIT_SALES") as "m0", sum("SALES_FACT_1997"."STORE_SALES") as "m1"
from "CUSTOMER" "CUSTOMER", "SALES_FACT_1997" "SALES_FACT_1997", "PRODUCT_CLASS" "PRODUCT_CLASS", "PRODUCT" "PRODUCT", "TIME_BY_DAY" "TIME_BY_DAY"
where "SALES_FACT_1997"."CUSTOMER_ID" = "CUSTOMER"."CUSTOMER_ID" and "CUSTOMER"."STATE_PROVINCE" = 'CA' and "SALES_FACT_1997"."PRODUCT_ID" = "PRODUCT"."PRODUCT_ID" and "PRODUCT"."PRODUCT_CLASS_ID" = "PRODUCT_CLASS"."PRODUCT_CLASS_ID" and "SALES_FACT_1997"."TIME_ID" = "TIME_BY_DAY"."TIME_ID" and "TIME_BY_DAY"."THE_YEAR" = 1997 and "TIME_BY_DAY"."QUARTER" = 'Q1' group by "CUSTOMER"."STATE_PROVINCE", "PRODUCT_CLASS"."PRODUCT_FAMILY", "TIME_BY_DAY"."THE_YEAR", "TIME_BY_DAY"."QUARTER"

Query builder in Ruby

Go to http://localhost:3000/mdx/builder and try following queries

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].children').
where('[Time].[1997].[Q1]', '[Customers].[USA].[CA]')

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].children').crossjoin('[Customers].[Canada]', '[Customers].[USA]').
where('[Time].[1997].[Q1]')

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].children').
where('[Time].[1997].[Q1].[1]', '[Time].[1997].[Q1].[2]').crossjoin('[Customers].[USA].[CA]', '[Customers].[USA].[OR]')

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].children').crossjoin('[Customers].[Canada]', '[Customers].[USA]').nonempty.
where('[Time].[1997].[Q1]')

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].children').order('[Measures].[Unit Sales]', :bdesc)

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].[Product Family].members', '[Products].[Brand Name].members').
  order('[Measures].[Unit Sales]', :bdesc)

olap.from('Sales').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('[Products].[Brand Name].members').top_count(5, '[Measures].[Store Sales]')

olap.from('Sales').
with_set('TopProducts').as('[Products].[Brand Name].members').
  top_percent(50, '[Measures].[Store Sales]').
with_set('AllOtherProducts').as('[Products].[Brand Name].members').except('TopProducts').
with_member('[Products].[All others]').as('AGGREGATE(AllOtherProducts)').
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]').
rows('TopProducts', '[Products].[All others]')

olap.from('Sales').
with_member('[Measures].[ProfitPct]').
  as('([Measures].[Store Sales] - [Measures].[Store Cost]) / [Measures].[Store Sales]',
  :format_string => 'Percent').
columns('[Measures].[Store Sales]', '[Measures].[ProfitPct]').
rows('[Products].children').crossjoin('[Customers].[USA].children').
  top_count(50, '[Measures].[Store Sales]').
where('[Time].[1997].[Q1]')

olap.from('Sales').
with_set('SelectedRows').
  as('[Products].children').crossjoin('[Customers].[USA].children').
with_member('[Measures].[Profit]').
  as('[Measures].[Store Sales] - [Measures].[Store Cost]').
columns('[Measures].[Profit]').
rows('SelectedRows')

Cube queries

You can try following cube queries in rails console

cube = Dwh.olap.cube('Sales')
cube.dimension_names                    # => ['Measures', 'Customers', 'Products', 'Time']
cube.dimensions                         # => array of dimension objects
cube.dimension('Customers')             # => customers dimension object
cube.dimension('Time').hierarchy_names  # => ['Time', 'Time.Weekly']
cube.dimension('Time').hierarchies      # => array of hierarchy objects
cube.dimension('Customers').hierarchy   # => default customers dimension hierarchy
cube.dimension('Customers').hierarchy.level_names
                                        # => ['(All)', 'Country', 'State Province', 'City', 'Name']
cube.dimension('Customers').hierarchy.levels
                                        # => array of hierarchy level objects
cube.dimension('Customers').hierarchy.level('Country').members
                                        # => array of all level members
cube.member('[Customers].[USA].[CA]')   # => lookup member by full name
cube.member('[Customers].[USA].[CA]').children
                                        # => get all children of member in deeper hierarchy level
cube.member('[Customers].[USA]').descendants_at_level('City')
                                        # => get all descendants of member in specified hierarchy level

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.