Writing a fixed-depth hierarchy creation process

Ivan Kulman -

Welcome to the second article in the MODLR Development series.

In this article we’re going to expand on the process knowledge and develop a basic fixed-depth hierarchy building process.

Firstly, let’s define a fixed-depth hierarchy: A fixed-depth hierarchy has the same number of levels between the top parent and the N-level (lowest-level) elements.

Product Family Product Category Product code Product name
Stationery Pens 0001 Black Pen 12pk
Food Biscuits 0011 Super Sweet Choc Biscuits

For this example, we’re going to use a csv file (attached at the bottom of the article):

  1. Open the left hand side menu and then navigate to “Manage Data"
    4.png
  2. Upload into new table on the right hand side of the screen:
    5.png
  3. Then point to the file location and click submit. Make sure that the “Create a new table from this file” option is selected.
    6.png

    Once uploaded, the table should appear in MODLR:

    7.png

At this stage everything is in MODLR, so we can start developing the process. We need to make sure that the process is setup correctly:

  • Action: Custom
  • Language: JavaScript

Once the new process is setup, we need to point it to the right data source:

  • Datasource: Internal Datastore
  • Method: Select a Table
  • Table: sample_dimension

The table should be visible for preview in the process creation page itself.

There are several tasks we’re going to achieve in one process:

  1. Create a dimension in the model
  2. Create a hierarchy in the dimension
  3. Generate all lowest-level elements
  4. Group the elements based on the source hierarchies
  5. Create an “All” element to display the totals in future reports
  6. Create and populate a name alias, so the reports can look presentable

To make the development process easier, we’re going to setup some variables to make it easier to refer to the dimension and top level elements. These variables need to be global, so we define them before the pre function:

var dimName = 'Fixed Depth Dimension';
var allElements = 'All SKUs';
var hierarchyName = 'Process Generated Hierarchy';
var aliasName = 'No - Name';

Then, in the begin section we are going to define everything that should be done once:

  1. Create dimension
    if( dimension.exists(dimName) != true ) {
        dimension.create(dimName, "standard");
        script.log("Dimension " + dimName + " has been successfully created");
    }
  2. Create hierarchy
    if( hierarchy.exists(dimName, hierarchyName) != true && dimension.exists(dimName) == true ) {
        hierarchy.create(dimName, hierarchyName);
        script.log("Hierarchy " + hierarchyName + "in the " + dimName + " dimension has been successfully created");
    }
    
  3. Create alias
    if( alias.exists(dimName, aliasName) != true && dimension.exists(dimName) == true) {
        alias.create(dimName, aliasName);
        script.log("Alias " + aliasName + "in the " + dimName + " dimension has been successfully created");
    }
    

Now we can proceed with the actual dimension building, this would be done in the data section because it is specific to each record.

The way we get items from the data source is by using record[‘field_name’].

So to make the development more streamlined and easier, it is recommended to get the variables separately from the actual code. In this case, the code simply gets the values from those columns and them trims them to make the dimension cleaner:

    var productFamily = record['product_family'].trim();
    var productCategory = record['product_category'].trim();
    var productCode = parseInt(record['product_code']);
    var productName = record['product_name'].trim();

And then let’s define the alias value as Product Code - Product Name.

var noNameAliasValue = productCode + " - " + productName;

There are two hierarchy structure creation functions in MODLR and both of them create both child and parent elements on the fly:

hierarchy.group(dimName, hierarchyName, c_parent, n_child);
hierarchy.structure(dimName, hierarchyName, c_parent, c_child);

The difference is that the hiearchy.group is used for the lowest level elements and hierarchies, while the hierarchy.structure function is used to manage consolidations.

In our case this is the hierarchy creation code:

hierarchy.group(dimName, hierarchyName, productCategory, productCode);
hierarchy.structure(dimName, hierarchyName,productFamily, productCategory);
hierarchy.structure(dimName, hierarchyName, allElements, productFamily);

And the alias setting code:

alias.set(dimName, aliasName, productCode, noNameAliasValue);

In the end, this is the process code:

var dimName = 'Fixed Depth Dimension';
var allElements = 'All SKUs';
var hierarchyName = 'Process Generated Hierarchy';
var aliasName = 'No - Name';

function pre() {
}

function begin() {
    script.log('process execution started.');

    if( dimension.exists(dimName) != true ) {
        dimension.create(dimName, "standard");
        script.log("Dimension " + dimName + " has been successfully created");
    }

    if( hierarchy.exists(dimName, hierarchyName) != true && dimension.exists(dimName) == true ) {
        hierarchy.create(dimName, hierarchyName);
        script.log("Hierarchy " + hierarchyName + "in the " + dimName + " dimension has been successfully created");
    }

    if( alias.exists(dimName, aliasName) != true && dimension.exists(dimName) == true) {
        alias.create(dimName, aliasName);
        script.log("Alias " + aliasName + "in the " + dimName + " dimension has been successfully created");
    }
}

function data(record) {
    var productFamily = record['product_family'].trim();
    var productCategory = record['product_category'].trim();
    var productCode = parseInt(record['product_code']);
    var productName = record['product_name'].trim();
    var noNameAliasValue = productCode + " - " + productName;
  
    hierarchy.group(dimName, hierarchyName, productCategory, productCode);
    hierarchy.structure(dimName, hierarchyName, productFamily, productCategory);
    hierarchy.structure(dimName, hierarchyName, allElements, productFamily);
    
    alias.set(dimName, aliasName, productCode, noNameAliasValue);

}

function end() {
    script.log('process execution finished.');
}

 

Then we can inspect the process results in the dimension explorer:

8.png

9.png

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.
Powered by Zendesk