/* Calculation Script name - WhizCalContribution Description - Contribution is the portion of the total value that belongs to any dimension. TRx contribution for product P1 =(TRx for product P1 / Total TRx)*100 Product Version - v66 Script Version - 1.0 ***Disclaimer - This is proprietary code of Whiz.AI. If you want to build on top of this computation script please make a copy/clone of this script and then alter the script which is copied or cloned. When version upgrade happens there are chances that this script may get modified hence any customization done by customer/partner developer may be overwritten. Key Functions - 1.Function name : compute purpose : perform the computation without creating join on dataSource input parameters : metaDataQuery output parameters : dataFrame 2.Function name : computeWithJoins purpose : perform the computation by creating join on dataSource input parameters : metaDataQuery output parameters : dataFrame Key variables - query : implicit variable outputMetricName : implicit variable WhizCalPaginationLib : The name of the object present in WhizCalPaginationLib.js(library script). execution scripts can call WhizCalPaginationLib scripts functions using given object. dataAccessManager: This class is exposed to scripts by Framework through implicit variable dataAccessManager. this acts as gateway to data exposed by the framework. A query can be fired through this instance to get the data. */ //**Start of Function code (() => { log.info("******************** WhizCalContribution **********************"); function compute(query) { //calling the function from library script const infoObj = WhizCalPaginationLib.modifyQueryAndGetInfo(query); // get list of dimensions from entity-configuration //dimensions and dim filters are set by application service const exceptDims = addonProps?.["defaultFilter"]?.["dynamicArgs"]?.["dimensions"]; const dimsToRemove = new Set(exceptDims); //names of dimensions configured. const dimNames = query.dimNames(); dimNames.forEach(item => dimsToRemove.add(item)); //copy()- creates deep copy from existing query //name(String name)- name for metadata query, this helps logging and identification of query const denomQuery = query.copy().name("WhizCalContribution_DenominatorQuery"); //removes all contents referring to each column present in the array from all places applicable denomQuery.removeColumns(Array.from(dimsToRemove)); //copy(String copyPrefix, MetadataQuery query)- creates deep copy of this aggregation,name of each aggregation is set as (copyPrefix+current name) const totalAggr = primaryAggr.copy("totalAggr", denomQuery); //clears the aggregations set on this query denomQuery.clearAggrs(); //adds given aggregation/post-aggregation to the query denomQuery.aggr(totalAggr); const joinOnCols = []; if (dimNames.length > 1) { //adds given dimension into the query denomQuery.dim(dimNames[1]); joinOnCols.push(dimNames[1]); } //name(String name)- name for metadata query, this helps logging and identification of query query.name("WhizCalContribution_NumeratorQuery"); //fires the MetadataQuery passed, returns DataFrame representing the response of the query const numeratorDf = dataAccessManager.fireQuery(query); //replaceOrderingColumn(String currentOrderingColum,String replacementColum)-Replaces any ordering clauses in the query with given column with ordering on new column denomQuery.replaceOrderingColumn(primaryAggr.column(), totalAggr.name()); //fires the MetadataQuery passed, returns DataFrame representing the response of the query const denominatorDf = dataAccessManager.fireQuery(denomQuery); //granularity()- returns effective granularity. So even when not set, returns granularity of type 'all' //type()- returns type of granularity like 'all', 'period', 'duration'. if (Granularity.TYPE_ALL == (denomQuery.granularity().type())) { //removes the given column from the DataFrame denominatorDf.removeColumn(TIMESTAMP_RESPONSE_COLUMN); } else if (joinOnCols.length > 0) { joinOnCols.push(TIMESTAMP_RESPONSE_COLUMN); } let finalDf; if (joinOnCols.length > 0) { //innerJoin(DataFrame otherDF, List<String> joinColumns, Map<String, Object> defaults) - creates response DF with inner join of this DF with other DF being passed finalDf = numeratorDf.innerJoin(denominatorDf, joinOnCols, {}); } else { //innerJoin(DataFrame otherDF)- creates response DF with inner join of this DF with other DF being passed. All common columns are assumed as join columns finalDf = numeratorDf.innerJoin(denominatorDf); } /* percent(String aggrName, Object value, Object outOf, double divByZeroResponse)- returns the Aggregation object, whose arithmetically result is 100*(value/base) aggrName: Name of the post aggregation for output results value: The value whose percentage is to be calculated against total (outOf) outOf: Total part of the percentage out of which 'value' is specified divByZeroResponse: The value that should be returned back when base value (outOf) is zero */ const aggr = Aggregation.percent(outputMetricName, primaryAggr.name(), totalAggr.name(), 0.0); //adds column with given aggregation, with name same as name of aggregation passed. The aggregation passed defines how would value of column to be added is derived finalDf.addColumn(aggr); //calling the function from library script return WhizCalPaginationLib.getFinalResponse(finalDf, infoObj); } function computeWithJoins(query) { //replaceOrderingColumn(String currentOrderingColum,String replacementColum)-Replaces any ordering clauses in the query with given column with ordering on new column query.replaceOrderingColumn(primaryAggr.column(), outputMetricName); //copy()- creates deep copy from existing query //name(String name)- name for metadata query, this helps logging and identification of query const numQuery = query.copy().name("WhizCalContribution_NumeratorQuery"); //returns offset set in metadataQuery const offset = numQuery.offset(); //returns limit set in metadataQuery const limit = numQuery.limit(); //returns shallow Copy of sort orders configured const order = numQuery.orderBy(); //limit(Integer limit)- sets limit on number of records that would be sent back by query //offset(Integer offset)- the number of first records with specified offset would be skipped //clearOrderBy()- clears the order by clauses set on this query numQuery.limit(null).offset(null).clearOrderBy(); //copy()- creates deep copy from existing query //name(String name)- name for metadata query, this helps logging and identification of query const denomQuery = numQuery.copy().name("WhizCalContribution_DenominatorQuery"); // get list of dimensions from entity-configuration const exceptDims = addonProps?.["defaultFilter"]?.["dynamicArgs"]?.["dimensions"]; const dimsToRemove = new Set(exceptDims); //names of dimensions configured. const dimNames = query.dimNames(); dimNames.forEach(item => dimsToRemove.add(item)); //removes all contents referring to each column present in the array from all places applicable denomQuery.removeColumns(Array.from(dimsToRemove)); //copy(String copyPrefix, MetadataQuery query)- creates deep copy of this aggregation,name of each aggregation is set as (copyPrefix+current name) const totalAggr = primaryAggr.copy("totalAggr", denomQuery); //clears the aggregations set on this query denomQuery.clearAggrs(); //adds given aggregation/post-aggregation to the query denomQuery.aggr(totalAggr); const joinOnCols = []; if (dimNames.length > 1) { //adds given dimension into the query denomQuery.dim(dimNames[1]); joinOnCols.push(dimNames[1]); } //granularity()- returns effective granularity. So even when not set, returns granularity of type 'all' //type()- returns type of granularity like 'all', 'period', 'duration'. if (Granularity.TYPE_ALL !== (denomQuery.granularity().type())) { joinOnCols.push(TIMESTAMP_RESPONSE_COLUMN); } const numDataSource = DataSource.innerQuery("numrDS", numQuery); const denDataSource = DataSource.innerQuery("denDS", denomQuery); let selectColumns = []; let aggregations = []; //adds given aggregation/post-aggregation to the query denomQuery.aggr(totalAggr); const numColumn = numDataSource.column(primaryAggr.name()); const denColumn = denDataSource.column(totalAggr.name()); selectColumns = [numColumn, denColumn]; aggregations.push(Aggregation.percent(outputMetricName, numColumn, denColumn, 0)); const joinOnColsMap = new Map(); joinOnCols.forEach(col => joinOnColsMap.set(col, col)); //creates a query with specified details const joinQuery = MetadataQuery.create() //Sets the model on which this query is to be run, model + dataSource combination decides the DB Table or Druid data source to be used to run the query .model(numQuery.model()) //name for metadata query, this helps logging and identification of query .name("WhizCalContribution_JoinQuery") //columns to be fetch from database .select(numQuery.dimNames()) .select(selectColumns.concat(aggregations)) //from(DBDataSource ds) -returns reference name of primary data source associated with this query .from(numDataSource) //leftJoinOn(DBDataSource dataSource, Map<String, String> joinColumnsLeftToRightMap)- create left join on datasource with given map of column .leftJoinOn(denDataSource, joinOnColsMap) //offset(Integer offset)- the number of first records with specified offset would be skipped .offset(offset) //limit(Integer limit)- sets limit on number of records that would be sent back by query .limit(limit) //orderBy(List sortData)- convenience method calling orderBy(String) or orderBy(SortData) depending on type of each element .orderBy(order) //granularity(Granularity granularity)- sets given granularity into the query .addonProperties(query.addonProperties()); //fires the MetadataQuery passed, returns DataFrame representing the response of the query return dataAccessManager.fireQuery(joinQuery); } // get value of apply_join_query variable from entity-configuration const applyJoin = addonProps?.["defaultFilter"]?.["dynamicArgs"]?.["apply_join_query"]; if (applyJoin) { return computeWithJoins(query); } else { return compute(query) } })();
/* ** configuration to be set in Computation metric ** default_filter:In this section's dynamicArgs sub-section, we have added, "apply_join_query" - flag to switch between two calculation approaches true - if join query needs to enable **The configuration below should be copied and pasted to calculate the contribution.* */ "default_filter": { "dynamicArgs": { "apply_join_query": true } }
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article