cube.js 动态schema 编译处理

cube.js 支持动态schema 的编译生成(只执行一次)

一些约定

基于asyncModule() 函数,自定义的schema 需要放schema 目录下(当然可以自己扩展resopitryFactory)
sql 以及drillMembers 需要是函数,函数的签名为()=>string

参考使用

  • schema 帮助函数
    sql 函数以及drillMembers 的处理,按照上边的约定
    schema/utils.js
 
export const convertStringPropToFunction = (propNames, dimensionDefinition) => {
  const newResult = { ...dimensionDefinition }
    propNames.forEach((propName) => {
    const propValue = newResult[propName]
 
      if (!propValue) {
      return
      }
    newResult[propName] = () => propValue
    })
    return newResult
  };
 
 
export const transformDimensions = (dimensions) => {
  return Object.keys(dimensions).reduce((result, dimensionName) => {
    const dimensionDefinition = dimensions[dimensionName]
      return {
      ...result,
      [dimensionName]: convertStringPropToFunction(
        ['sql'],
        dimensionDefinition
      )
    }
    }, {})
  };
 
 
export const transformMeasures = (measures) => {
  return Object.keys(measures).reduce((result, dimensionName) => {
    const dimensionDefinition = measures[dimensionName]
      return {
      ...result,
      [dimensionName]: convertStringPropToFunction(
        ['sql', 'drillMembers'],
        dimensionDefinition
      )
    }
    }, {})
  };
  • schema 动态生成
    基于node-fetch 通过api 获取定义 asyncModule 是比较重要的
 
const fetch = require('node-fetch');
import {
  transformDimensions,
  transformMeasures,
} from './utils';
asyncModule(async () => {
  const dynamicCubes = await (
    await fetch('http://localhost:8080/app.json')
  ).json();
 
 
  console.log(dynamicCubes);
  dynamicCubes.forEach((dynamicCube) => {
    const dimensions = transformDimensions(dynamicCube.dimensions);
    const measures = transformMeasures(dynamicCube.measures);
 
 
    cube(dynamicCube.title, {
      sql: dynamicCube.sql,
      dimensions,
      measures,
      preAggregations: {
        main: {
          type: `originalSql`,
        },
      },
    });
  });
});

app.json

[
  {
    "preAggregations": {
      "mydemo": {
        "type": "autoRollup",
        "measureReferences": [
          "DynamicCubeSchema.price"
        ],
        "dimensionReferences": [
          "name"
        ],
        "external": true
      }
    },
    "dimensions": {
      "name": {
        "sql": "name",
        "type": "string"
      }
    },
    "measures": {
      "price": {
        "drillMembers": [
          "name",
          "id"
        ],
        "type": "count"
      }
    },
    "title": "DynamicCubeSchema",
    "sql": "SELECT * FROM demoapp"
  }
]

运行&&效果

  • 入口
    index.js 基于throng 提升多线程能力
 
const CubejsServer = require('@cubejs-backend/server');
const cubejs = require("./cube")
const throng = require('throng')
const WORKERS = process.env.WEB_CONCURRENCY || 2
const server = new CubejsServer(cubejs);
throng(WORKERS, start)
function start(){
    server
    .listen()
    .then(({ version, port }) => {
      console.log(`🚀 Cube.js server (${version}) is listening on ${port}`);
    })
    .catch((e) => {
      console.error('Fatal error during server start: ');
      console.error(e.stack || e);
    });
}
  • 启动
    需要先启动提供动态schema 的api 然后提供cube.js 效果

     

     

说明

完整代码可以参考GitHub https://github.com/rongfengliang/cubejs-pre-age/tree/v2 包含了cubestore的使用,但是一些不太好的地方是es6 string 模版的
支持,因为api 的特性,但是我们可以通过扩展function 支持,参考

 
 String.prototype.interpolate = function(params) {
      const names = Object.keys(params);
      const vals = Object.values(params);
      return new Function(...names, `return \`${this}\`;`)(...vals);
    }

参考资料

https://cube.dev/docs/schema-execution-environment#cube-js-globals-cube-and-others
https://cube.dev/docs/schema/dynamic-schema-creation
https://github.com/rongfengliang/cubejs-pre-age/tree/v2

posted on 2021-01-23 23:55  荣锋亮  阅读(298)  评论(0编辑  收藏  举报

导航