SlideShare ist ein Scribd-Unternehmen logo
1 von 26
Downloaden Sie, um offline zu lesen
mondrian-olap 
JRuby library
Raimonds Simanovskis 
@rsim 
github.com/rsim
Mondrian! 
is nice…
But I don’t like 
Java and XML 
so much…
And I like! 
Ruby!
object-oriented 
dynamic 
programming language 
simple from outside 
powerful inside 
Yukihiro 
Matsumoto 
or “Matz”
What is! 
mondrian-olap! 
JRuby gem?
http://github.com/rsim/ 
mondrian-olap
Mondrian 3.x schema 
schema = Mondrian::OLAP::Schema.define do definition 
cube 'Sales' do 
table 'sales' 
dimension 'Customers', foreign_key: 'customer_id' do 
hierarchy has_all: true, all_member_name: 'All Customers', primary_key: 'id' do 
table 'customers' 
level 'Country', column: 'country', unique_members: true 
level 'State Province', column: 'state_province', unique_members: true 
level 'City', column: 'city', unique_members: false 
level 'Name', column: 'fullname', unique_members: false 
end 
end 
dimension 'Time', foreign_key: 'time_id', type: 'TimeDimension' do 
hierarchy has_all: false, primary_key: 'id' do 
table 'time' 
level 'Year', column: 'the_year', type: 'Numeric', unique_members: true, 
level_type: 'TimeYears' 
level 'Quarter', column: 'quarter', unique_members: false, 
level_type: 'TimeQuarters' 
level 'Month', column: 'month_of_year', type: 'Numeric', unique_members: false, 
level_type: 'TimeMonths' 
end 
end 
measure 'Unit Sales', column: 'unit_sales', aggregator: 'sum' 
measure 'Store Sales', column: 'store_sales', aggregator: 'sum' 
end 
end
Mondrian connection 
olap = Mondrian::OLAP::Connection.create( 
driver: 'mysql', 
host: 'localhost', 
database: 'mondrian_test', 
username: 'mondrian_user', 
password: 'secret', 
schema: schema 
)
MDX queries 
result = olap.execute <<-MDX 
SELECT {[Measures].[Unit Sales], [Measures].[Store Sales]} ON COLUMNS, 
{[Products].children} ON ROWS 
FROM [Sales] 
WHERE ([Time].[2010].[Q1], [Customers].[USA].[CA]) 
MDX 
! 
result.axes_count # => 2 
result.column_names # => ["Unit Sales", "Store Sales"] 
result.column_full_names # => ["[Measures].[Unit Sales]", 
# "[Measures].[Store Sales]"] 
result.row_names # => e.g. ["Drink", "Food", "Non-Consumable"] 
result.row_full_names # => e.g. ["[Products].[Drink]", "[Products]. 
[Food]", 
# "[Products].[Non-Consumable]"] 
result.values # => [[..., ...], [..., ...], [..., ...]] 
# (three rows, each row containing value for 
# "unit sales" and "store sales")
Query builder 
olap.from('Sales'). 
columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]'). 
rows('[Products].children'). 
where('[Time].[2010].[Q1]', '[Customers].[USA].[CA]'). 
execute
Query builder 
olap.from('Sales'). 
with_member('[Measures].[ProfitPct]'). 
as('Val((Measures.[Store Sales] - Measures.[Store Cost]) / 
Measures.[Store Sales])', 
format_string: 'Percent'). 
columns('[Measures].[Store Sales]', '[Measures].[ProfitPct]'). 
rows('[Products].children'). 
crossjoin('[Customers].[Canada]', '[Customers].[USA]'). 
top_count(50, '[Measures].[Store Sales]'). 
where('[Time].[2010].[Q1]'). 
execute
Cube and member 
queries 
cube = 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
User defined 
MDX functions 
schema = Mondrian::OLAP::Schema.define do 
# ... cube definitions ... 
user_defined_function 'Factorial' do 
ruby do 
parameters :numeric 
returns :numeric 
def call(n) 
n <= 1 ? 1 : n * call(n - 1) 
end 
end 
end 
user_defined_function 'UpperName' do 
ruby do 
parameters :member 
returns :string 
syntax :property 
def call(member) 
member.getName.upcase 
end 
end 
end 
end
UDF in JavaScript 
schema = Mondrian::OLAP::Schema.define do 
# ... cube definitions ... 
user_defined_function 'Factorial' do 
javascript <<-JS 
function getParameterTypes() { 
return new Array( 
new mondrian.olap.type.NumericType()); 
} 
function getReturnType(parameterTypes) { 
return new mondrian.olap.type.NumericType(); 
} 
function execute(evaluator, arguments) { 
var n = arguments[0].evaluateScalar(evaluator); 
return factorial(n); 
} 
function factorial(n) { 
return n <= 1 ? 1 : n * factorial(n - 1); 
} 
JS 
end 
end
JavaScript is 
OK … but 
CoffeeScript 
is better!
Sample CoffeeScript 
# Assignment: 
number = 42 
opposite = true 
# Conditions: 
number = -42 if opposite 
# Functions: 
square = (x) -> x * x 
# Arrays: 
list = [1, 2, 3, 4, 5] 
# Objects: 
math = 
root: Math.sqrt 
square: square 
cube: (x) -> x * square x 
# Splats: 
race = (winner, runners...) -> 
print winner, runners 
# Existence: 
alert "I knew it!" if elvis? 
# Array comprehensions: 
cubes = (math.cube num for num in list)
UDF in CoffeeScript 
schema = Mondrian::OLAP::Schema.define do 
# ... cube definitions ... 
user_defined_function 'Factorial' do 
coffeescript <<-JS 
parameters: ["Numeric"] 
returns: "Numeric" 
execute: (n) -> 
if n <= 1 then 1 else n * @execute(n - 1) 
JS 
end 
end
Cell, property, member 
formatters in 
Ruby and CoffeeScript 
cell_formatter { ruby {|value| "%020d" % value} } 
property_formatter do 
ruby do |member, property_name, property_value| 
property_value.upcase 
end 
end 
member_formatter { ruby {|member| member.getName().upcase } } 
! 
cell_formatter do 
coffeescript <<-JS 
s = value.toString() 
s = "0" + s while s.length < 20 
s 
JS 
end 
member_formatter { coffeescript "member.getName().toUpperCase()" } 
property_formatter { coffeescript "propertyValue.toUpperCase()" }
Next idea:! 
More 
CoffeeScript
Next idea: 
Mondrian schema 
in CoffeeScript 
@Schema -> 
@Cube 'Sales', -> 
@Table 'sales' 
@Dimension 'Customers', foreignKey: 'customer_id', -> 
@Hierarchy hasAll: true, allMemberName: 'All Customers', primaryKey: 'id', -> 
@Table 'customers' 
@Level 'Country', column: 'country', uniqueMembers: true 
@Level 'State Province', column: 'state_province', uniqueMembers: true 
@Level 'City', column: 'city', uniqueMembers: false 
@Level 'Name', column: 'fullname', uniqueMembers: false 
@Dimension 'Time', foreignKey: 'time_id', type: 'TimeDimension', -> 
@Hierarchy hasAll: false, primaryKey: 'id', -> 
@Table 'time' 
@Level 'Year', column: 'the_year', type: 'Numeric', uniqueMembers: true,  
levelType: 'TimeYears' 
@Level 'Quarter', column: 'quarter', uniqueMembers: false,  
levelType: 'TimeQuarters' 
@Level 'Month', column: 'month_of_year', type: 'Numeric', uniqueMembers: false,  
levelType: 'TimeMonths' 
@Measure 'Unit Sales', column: 'unit_sales', aggregator: 'sum' 
@Measure 'Store Sales', column: 'store_sales', aggregator: 'sum'
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
pauldix
 
Gail villanueva add muscle to your wordpress site
Gail villanueva   add muscle to your wordpress siteGail villanueva   add muscle to your wordpress site
Gail villanueva add muscle to your wordpress site
references
 

Was ist angesagt? (20)

Solid angular
Solid angularSolid angular
Solid angular
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
AngularJS
AngularJSAngularJS
AngularJS
 
Template post
Template postTemplate post
Template post
 
Optimizing Magento by Preloading Data
Optimizing Magento by Preloading DataOptimizing Magento by Preloading Data
Optimizing Magento by Preloading Data
 
날로 먹는 Django admin 활용
날로 먹는 Django admin 활용날로 먹는 Django admin 활용
날로 먹는 Django admin 활용
 
Emberjs as a rails_developer
Emberjs as a rails_developer Emberjs as a rails_developer
Emberjs as a rails_developer
 
Jquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript BasicsJquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript Basics
 
Django Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & Witchery
 
WordPress Capabilities Magic
WordPress Capabilities MagicWordPress Capabilities Magic
WordPress Capabilities Magic
 
Angular js form validation shashi-19-7-16
Angular js form validation shashi-19-7-16Angular js form validation shashi-19-7-16
Angular js form validation shashi-19-7-16
 
Get AngularJS Started!
Get AngularJS Started!Get AngularJS Started!
Get AngularJS Started!
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Working with Javascript in Rails
Working with Javascript in RailsWorking with Javascript in Rails
Working with Javascript in Rails
 
Oleksandr Masovets. Forms in Drupal. Drupal Camp Kyiv 2011
Oleksandr Masovets. Forms in Drupal. Drupal Camp Kyiv 2011Oleksandr Masovets. Forms in Drupal. Drupal Camp Kyiv 2011
Oleksandr Masovets. Forms in Drupal. Drupal Camp Kyiv 2011
 
Drupal Form Api
Drupal Form ApiDrupal Form Api
Drupal Form Api
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
Gail villanueva add muscle to your wordpress site
Gail villanueva   add muscle to your wordpress siteGail villanueva   add muscle to your wordpress site
Gail villanueva add muscle to your wordpress site
 
HTML Form Part 1
HTML Form Part 1HTML Form Part 1
HTML Form Part 1
 
Angular js form validation with ngmessages shashi-19-7-16
Angular js form validation with ngmessages shashi-19-7-16Angular js form validation with ngmessages shashi-19-7-16
Angular js form validation with ngmessages shashi-19-7-16
 

Ähnlich wie mondrian-olap JRuby library

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)
Raimonds Simanovskis
 
The Future of Rubymotion
The Future of RubymotionThe Future of Rubymotion
The Future of Rubymotion
Clay Allsopp
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 

Ähnlich wie mondrian-olap JRuby library (20)

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)Multidimensional Data Analysis with Ruby (sample)
Multidimensional Data Analysis with Ruby (sample)
 
The Future of Rubymotion
The Future of RubymotionThe Future of Rubymotion
The Future of Rubymotion
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Rails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowRails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not Know
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
A piece of sugar in your client-side development
A piece of sugar in your client-side developmentA piece of sugar in your client-side development
A piece of sugar in your client-side development
 
Functional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartFunctional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smart
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
 
Ruby on Rails testing with Rspec
Ruby on Rails testing with RspecRuby on Rails testing with Rspec
Ruby on Rails testing with Rspec
 
Profiling Mondrian MDX Requests in a Production Environment
Profiling Mondrian MDX Requests in a Production EnvironmentProfiling Mondrian MDX Requests in a Production Environment
Profiling Mondrian MDX Requests in a Production Environment
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 

Mehr von Raimonds Simanovskis

Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
How to Adopt Agile at Your Organization
How to Adopt Agile at Your OrganizationHow to Adopt Agile at Your Organization
How to Adopt Agile at Your Organization
Raimonds Simanovskis
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
Raimonds Simanovskis
 

Mehr von Raimonds Simanovskis (20)

Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
 
Data Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data AnalysisData Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data Analysis
 
eazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applicationseazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applications
 
Atvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze LatvijāAtvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze Latvijā
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVM
 
Agile Operations or How to sleep better at night
Agile Operations or How to sleep better at nightAgile Operations or How to sleep better at night
Agile Operations or How to sleep better at night
 
TDD - Why and How?
TDD - Why and How?TDD - Why and How?
TDD - Why and How?
 
Analyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and ProfitAnalyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and Profit
 
PL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be FunPL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be Fun
 
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizationsopendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRuby
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRuby
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
 
How to Adopt Agile at Your Organization
How to Adopt Agile at Your OrganizationHow to Adopt Agile at Your Organization
How to Adopt Agile at Your Organization
 
PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!PL/SQL Unit Testing Can Be Fun!
PL/SQL Unit Testing Can Be Fun!
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
 

Kürzlich hochgeladen

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Kürzlich hochgeladen (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 

mondrian-olap JRuby library

  • 2. Raimonds Simanovskis @rsim github.com/rsim
  • 4. But I don’t like Java and XML so much…
  • 5. And I like! Ruby!
  • 6. object-oriented dynamic programming language simple from outside powerful inside Yukihiro Matsumoto or “Matz”
  • 7.
  • 8.
  • 11. Mondrian 3.x schema schema = Mondrian::OLAP::Schema.define do definition cube 'Sales' do table 'sales' dimension 'Customers', foreign_key: 'customer_id' do hierarchy has_all: true, all_member_name: 'All Customers', primary_key: 'id' do table 'customers' level 'Country', column: 'country', unique_members: true level 'State Province', column: 'state_province', unique_members: true level 'City', column: 'city', unique_members: false level 'Name', column: 'fullname', unique_members: false end end dimension 'Time', foreign_key: 'time_id', type: 'TimeDimension' do hierarchy has_all: false, primary_key: 'id' do table 'time' level 'Year', column: 'the_year', type: 'Numeric', unique_members: true, level_type: 'TimeYears' level 'Quarter', column: 'quarter', unique_members: false, level_type: 'TimeQuarters' level 'Month', column: 'month_of_year', type: 'Numeric', unique_members: false, level_type: 'TimeMonths' end end measure 'Unit Sales', column: 'unit_sales', aggregator: 'sum' measure 'Store Sales', column: 'store_sales', aggregator: 'sum' end end
  • 12. Mondrian connection olap = Mondrian::OLAP::Connection.create( driver: 'mysql', host: 'localhost', database: 'mondrian_test', username: 'mondrian_user', password: 'secret', schema: schema )
  • 13. MDX queries result = olap.execute <<-MDX SELECT {[Measures].[Unit Sales], [Measures].[Store Sales]} ON COLUMNS, {[Products].children} ON ROWS FROM [Sales] WHERE ([Time].[2010].[Q1], [Customers].[USA].[CA]) MDX ! result.axes_count # => 2 result.column_names # => ["Unit Sales", "Store Sales"] result.column_full_names # => ["[Measures].[Unit Sales]", # "[Measures].[Store Sales]"] result.row_names # => e.g. ["Drink", "Food", "Non-Consumable"] result.row_full_names # => e.g. ["[Products].[Drink]", "[Products]. [Food]", # "[Products].[Non-Consumable]"] result.values # => [[..., ...], [..., ...], [..., ...]] # (three rows, each row containing value for # "unit sales" and "store sales")
  • 14. Query builder olap.from('Sales'). columns('[Measures].[Unit Sales]', '[Measures].[Store Sales]'). rows('[Products].children'). where('[Time].[2010].[Q1]', '[Customers].[USA].[CA]'). execute
  • 15. Query builder olap.from('Sales'). with_member('[Measures].[ProfitPct]'). as('Val((Measures.[Store Sales] - Measures.[Store Cost]) / Measures.[Store Sales])', format_string: 'Percent'). columns('[Measures].[Store Sales]', '[Measures].[ProfitPct]'). rows('[Products].children'). crossjoin('[Customers].[Canada]', '[Customers].[USA]'). top_count(50, '[Measures].[Store Sales]'). where('[Time].[2010].[Q1]'). execute
  • 16. Cube and member queries cube = 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
  • 17. User defined MDX functions schema = Mondrian::OLAP::Schema.define do # ... cube definitions ... user_defined_function 'Factorial' do ruby do parameters :numeric returns :numeric def call(n) n <= 1 ? 1 : n * call(n - 1) end end end user_defined_function 'UpperName' do ruby do parameters :member returns :string syntax :property def call(member) member.getName.upcase end end end end
  • 18. UDF in JavaScript schema = Mondrian::OLAP::Schema.define do # ... cube definitions ... user_defined_function 'Factorial' do javascript <<-JS function getParameterTypes() { return new Array( new mondrian.olap.type.NumericType()); } function getReturnType(parameterTypes) { return new mondrian.olap.type.NumericType(); } function execute(evaluator, arguments) { var n = arguments[0].evaluateScalar(evaluator); return factorial(n); } function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); } JS end end
  • 19. JavaScript is OK … but CoffeeScript is better!
  • 20.
  • 21. Sample CoffeeScript # Assignment: number = 42 opposite = true # Conditions: number = -42 if opposite # Functions: square = (x) -> x * x # Arrays: list = [1, 2, 3, 4, 5] # Objects: math = root: Math.sqrt square: square cube: (x) -> x * square x # Splats: race = (winner, runners...) -> print winner, runners # Existence: alert "I knew it!" if elvis? # Array comprehensions: cubes = (math.cube num for num in list)
  • 22. UDF in CoffeeScript schema = Mondrian::OLAP::Schema.define do # ... cube definitions ... user_defined_function 'Factorial' do coffeescript <<-JS parameters: ["Numeric"] returns: "Numeric" execute: (n) -> if n <= 1 then 1 else n * @execute(n - 1) JS end end
  • 23. Cell, property, member formatters in Ruby and CoffeeScript cell_formatter { ruby {|value| "%020d" % value} } property_formatter do ruby do |member, property_name, property_value| property_value.upcase end end member_formatter { ruby {|member| member.getName().upcase } } ! cell_formatter do coffeescript <<-JS s = value.toString() s = "0" + s while s.length < 20 s JS end member_formatter { coffeescript "member.getName().toUpperCase()" } property_formatter { coffeescript "propertyValue.toUpperCase()" }
  • 24. Next idea:! More CoffeeScript
  • 25. Next idea: Mondrian schema in CoffeeScript @Schema -> @Cube 'Sales', -> @Table 'sales' @Dimension 'Customers', foreignKey: 'customer_id', -> @Hierarchy hasAll: true, allMemberName: 'All Customers', primaryKey: 'id', -> @Table 'customers' @Level 'Country', column: 'country', uniqueMembers: true @Level 'State Province', column: 'state_province', uniqueMembers: true @Level 'City', column: 'city', uniqueMembers: false @Level 'Name', column: 'fullname', uniqueMembers: false @Dimension 'Time', foreignKey: 'time_id', type: 'TimeDimension', -> @Hierarchy hasAll: false, primaryKey: 'id', -> @Table 'time' @Level 'Year', column: 'the_year', type: 'Numeric', uniqueMembers: true, levelType: 'TimeYears' @Level 'Quarter', column: 'quarter', uniqueMembers: false, levelType: 'TimeQuarters' @Level 'Month', column: 'month_of_year', type: 'Numeric', uniqueMembers: false, levelType: 'TimeMonths' @Measure 'Unit Sales', column: 'unit_sales', aggregator: 'sum' @Measure 'Store Sales', column: 'store_sales', aggregator: 'sum'