is an hypercube of data
Description | Installation | API | License
An OLAP cube is a multidimensional array of data you can explore and analyze. Here you will find an engine that could feed a graphic viewer.
With npm do
npm install olap-cube
Add this to your HTML page
<script src="https://unpkg.com/olap-cube/dist/olap-cube.min.js"></script>
All code in this section is run and tested in this single file. Note also that
- Everything is immutable, all attributes are static.
- Operators are chainable and they always return a brand new instance.
- @param
{Object}
arg - @param
{Array}
arg.dimensions - @param
{Array}
arg.points - @param
{Array}
arg.fields - @param
{Array}
arg.data in the format data[pointIndex][fieldIndex]
const Table = require('olap-cube').model.Table
const table = new Table({
dimensions: ['year', 'month'],
fields: ['revenue'],
points: [[2016, 'Jan']],
data: [[100]]
})
console.log(table) // Table {
// dimensions: ['year', 'month'],
// fields: ['revenue']
// }
Attribute structure holds necessary information to clone a table excluding its data.
Create an empty table
const emptyTable = new Table(table.structure)
The (hyper)cube dimensions.
One common dimension in Business Intelligence is time: it can have different granularities, like year, month, day, etc.
console.log(table.dimensions) // [ 'year', 'month' ]
The names of the data fields.
console.log(table.fields) // [ 'revenue' ]
Attribute header concatenates dimension names and field names.
console.log(table.header) // ['year', 'month', 'revenue']
Add a set of rows to the table.
- @param
{Object}
data - @param
{Array}
data.header - @param
{Array}
data.rows - @returns
{Object}
table
Every row is an object which attributes are either a dimension or a field.
const table2 = emptyTable.addRows({
header: ['year', 'month', 'revenue'],
rows: [
[ 2015, 'Nov', 80 ],
[ 2015, 'Dec', 90 ],
[ 2016, 'Jan', 100 ],
[ 2016, 'Feb', 170 ],
[ 2016, 'Mar', 280 ],
[ 2017, 'Feb', 177 ],
[ 2017, 'Apr', 410 ]
]
})
Attribute data holds the facts of the table.
console.log(table2.data) // [[ 80 ],
// [ 90 ],
// [ 100 ],
// [ 170 ],
// [ 280 ],
// [ 177 ],
// [ 410 ]]
Attribute rows holds the dimensions and the facts of the table.
console.log(table2.rows) // [[ 2015, 'Nov', 80 ],
// [ 2015, 'Dec', 90 ],
// [ 2016, 'Jan', 100 ],
// [ 2016, 'Feb', 170 ],
// [ 2016, 'Mar', 280 ],
// [ 2017, 'Feb', 177 ],
// [ 2017, 'Apr', 410 ]]
The points are an ordered set of coordinates.
In this case you can see 6 points with coordinates:
- year
- month
console.log(table2.points) // [[ 2015, 'Nov' ],
// [ 2015, 'Dec' ],
// [ 2016, 'Jan' ],
// [ 2016, 'Feb' ],
// [ 2016, 'Feb' ],
// [ 2017, 'Apr' ]]
Slice operator picks a rectangular subset of a cube by choosing a single value of its dimensions.
- @param
{String}
dimension - @param
{*}
filter - @returns
{Object}
table
Consider the following example, where a slice with 2016 year is created.
const table3 = table2.slice('year', 2016)
console.log(table3.points) // [[ 2016, 'Jan' ],
// [ 2016, 'Feb' ],
// [ 2016, 'Mar' ]]
console.log(table3.data) // [[ 100 ],
// [ 170 ],
// [ 280 ]]
Dice operator picks a subcube by choosing a specific values of multiple dimensions.
- @param
{Function}
selector - @returns
{Object}
table
Consider the following example, where a dice excluding one month is created.
const onlyFebruary = (point) => point[1] !== 'Feb'
const table4 = table2.dice(onlyFebruary)
console.log(table4.points) // [[ 2015, 'Nov' ],
// [ 2015, 'Dec' ],
// [ 2016, 'Jan' ],
// [ 2016, 'Mar' ],
// [ 2017, 'Apr' ]]
console.log(table4.data) // [[ 80 ],
// [ 90 ],
// [ 100 ],
// [ 280 ],
// [ 410 ]]
A roll-up involves summarizing the data along a dimension. The summarization rule might be computing totals along a hierarchy or applying a set of formulas such as "profit = sales - expenses".
- @param
{String}
dimension - @param
{Array}
fields - @param
{Function}
aggregator - @param
{*}
initialValue that will be passed to Array.prototype.reduce(). - @returns
{Object}
table
const table5 = new Table({
dimensions: ['continent', 'country'],
fields: ['numStores']
})
// NOTA BENE: Remember that tables are immuTables ☺.
const table6 = table5.addRows({
header: [ 'continent', 'country', 'numStores' ],
rows: [
[ 'Europe', 'Norway', 20 ],
[ 'Europe', 'Denmark', 48 ],
[ 'Europe', 'Germany', 110 ],
[ 'Europe', 'Portugal', 17 ],
[ 'Asia', 'China', 280 ],
[ 'Asia', 'Russia', 161 ],
[ 'Asia', 'Thailand', 120 ]
]
})
// Input tables and rolled up table has only one field,
// with the same name: numStores.
// Actually the aggregator is a reducer that will receive in input an
// array of fields from the input table, and will output an array of
// fields to the rolled up table.
const summation = (sum, value) => {
return [sum[0] + value[0]]
}
const initialValue = [0]
const table7 = table6.rollup('continent', ['numStores'], summation, initialValue)
console.log(table7.rows) // [[ 'Europe', 195 ],
// [ 'Asia', 561 ]]