![e0154d0e5327aeb4e904e0e93575be99.png](https://i-blog.csdnimg.cn/blog_migrate/6646adc4d818924e153c2587b486a2db.jpeg)
Cube.js是一个用于构建分析 web 应用程序的开源框架,主要用于构建内部的商业智能工具或将面向客户的分析添加到现有的应用程序当中。大多数情况下,构建此类应用程序的第一步是分析仪表板。通常从“在管理面板中添加一个分析仪表板”开始,然后就像软件开发中经常发生的那样,事情会变得更加复杂。
当开始使用 Cube.js 时,会想要构建一个工具,它起初很简单,但在功能、复杂性和数据量方面很容易扩展。Cube.js 为未来的分析系统奠定坚实的基础,无论是独立的应用程序还是嵌入到现有的分析系统中。
本教程可以视为“Cube.js 101”,它介绍了从数据库到可视化的第一个仪表板的基本设计步骤。
最终仪表板的现场演示可在此处获得。完整的源代码在 GitHub 上。
架构
大多数现代 web 应用程序都是作为单页面应用程序构建的,前端与后端分离。遵循微服务架构,后端通常也会分成多个服务。
通常,Cube.js 的后端作为服务运行,管理与数据库的连接,包括查询队列、缓存、预聚合等。同时为前端应用程序公开一个 API,用于构建仪表板和其他分析功能。
![10cc59a13b139c51bc4770887e9d95a0.png](https://i-blog.csdnimg.cn/blog_migrate/93d88b792aa995ae9232d03b3f4cedf6.jpeg)
后端
分析从数据产生并驻留在数据库中开始,如果用户已经有一个适用于应用程序的数据库,通常它可以直接用于分析。现代流行的数据库,如 Postgres 或 MySQL,都可以做简单的分析工作,这里的简单指的是行数少于 10 亿的数据量。
另外,MongoDB 也可以,不过需要添加 MongoDB Connector for BI。它允许在 MongoDB 数据之上执行 SQL 代码。这是免费的,可以从 MongoDB 网站直接下载。需要注意的是,出于性能问题的考虑,直接在生产数据库上运行分析查询是不好的做法。所以,即使 Cube.js 可以显著减少数据库的工作量,但仍然建议连接到副本。
总而言之,如果使用 Postgres 或 MySQL,只需创建一个副本就可以了。如果您使用 MongoDB,请下载 MongoDB Connector for BI 并创建副本。
如果没有构建仪表板的任何数据,可以加载示例中的电子商务 Postgres 数据集。
![519f34310d0f5cdfcf91463fe8c57bf6.png](https://i-blog.csdnimg.cn/blog_migrate/d99a71ee103911bd763bbab9ca26b8f2.jpeg)
数据库中有数据,就可以开始创建 Cube.js 的后端服务。在终端中运行以下命令:
![e30c66f4fc83405f40d55592387d1cbf.png](https://i-blog.csdnimg.cn/blog_migrate/b1facf969b120d0a81208f4e647ed027.jpeg)
上面的命令安装 Cube.js CLI,并创建一个新服务,配置为可以与 Postgres 数据库一起使用。
Cube.js 使用环境变量进行配置,环境变量以 CUBEJS_ 开头。要配置与数据库的连接,需要指定数据库的类型和名称。在 Cube.js 项目文件夹中,替换.env 的以下内容:
![7e2ff5f08030977ba9843e9f95e6a236.png](https://i-blog.csdnimg.cn/blog_migrate/69bd934ac3cd859885e8bb6f32ff0e07.jpeg)
Cube.js 数据 Schema
下一步是创建一个Cube.js 数据 Schema。Cube.js 利用数据 Schema 生成 SQL 代码,该代码将在数据库中执行。数据 Schema 不是 SQL 的替代品,它旨在使 SQL 可重用并赋予其结构,同时保留其所有功能。数据 Schema 的基本元素是 measures 和 dimensions。
,
Measure 被称为定量数据,例如单位销售数、唯一访问量、利润等。
Dimension 被称为分类数据,例如状态、性别、产品名称或时间单位(例如,日、周、月)。
通常,模式文件位于 schema 文件夹中。以下是架构的示例,可用于描述用户的数据。
![a9560c558544a4b51a64cef61ba0f843.png](https://i-blog.csdnimg.cn/blog_migrate/6b344dd603a88aab6871df3cc22b0a0f.jpeg)
现在,通过上述 Schema,可以向 Cube.js 后端发送有关用户数据的查询。Cube.js 查询是纯 JavaScript 对象。通常情况下,它有一个或多个 measures、dimensions 和 timeDimensions。
如果要回答“用户在哪里?”这个问题,可以将以下查询发送到 Cube.js:
![c2a817fdb9e35e7f20c8654ef1200bdf.png](https://i-blog.csdnimg.cn/blog_migrate/f683255b0f10efcd4497db769e4d9d0b.jpeg)
Cube.js 将根据 Schema 生成所需的 SQL,执行它并将结果发回。
我们可以创建一个稍微复杂的查询,添加一个 timeDimensions,看看去年不同城市的比例在每个月是如何变化的。为此,需要添加 signedUp 时间维度,按月分组,并仅包含去年的注册。
![4f6da2301fb73ff86daa28bb0553d6ec.png](https://i-blog.csdnimg.cn/blog_migrate/02344472b5742b81d5ebbdcf4a9582ab.jpeg)
Cube.js 还可以根据数据库的表生成简单的 Schema,并需要为仪表板生成所需的 Schema,启动一个供开发的服务器。
![b0967c28a9b1f92418fbe26fcc594808.png](https://i-blog.csdnimg.cn/blog_migrate/32a8fcfb11710f638170dadde1bd53fa.jpeg)
可以通过在http://localhost:4000打开开发后台,检查生成的 Schema 并发送测试的查询。
前端
通过 Cube.js 的 React 客户端,可以使用 React 来构建前端和仪表板。也可以使用任何框架或只使用 vanilla JavaScript 来构建 Cube.js 的前端,这个教程将向您展示如何在纯 JavaScript 中构建仪表板。我们将使用 React 团队正式支持的 Create React App 来设置所有内容,它打包了 React 应用程序的所有依赖项,可以轻松地开始使用新项目。在终端中运行以下命令:
![b987f2a0e3cc9daed3db6a96615e646a.png](https://i-blog.csdnimg.cn/blog_migrate/6e5d7f4dc5cff51b5b04cd938f3700db.jpeg)
最后一行在端口 3000 上启动服务器,并通过http://localhost:3000打开 web 浏览器。
我们将使用 Reactstrap 来构建我们的 UI,它是 Bootstrap 4 的 React wrapper。用 NPM 来安装 Reactstrap 和 Bootstrap。Reactstrap 不包括 Bootstrap CSS,所以需要单独安装:
![e602b5df82a65422c3c260223d66d668.png](https://i-blog.csdnimg.cn/blog_migrate/4c62ce2b42526e89404dd86ac83ac2a7.jpeg)
导入./index.css 之前,导入 src/index.js 文件中的 Bootstrap CSS:
![742e6cefafadcae0ddcddc2427dbb836.png](https://i-blog.csdnimg.cn/blog_migrate/5deb29e70ef81b5a9339783f178878fe.jpeg)
现在,我们已准备好使用 Reactstrap 组件。
下一步是安装 Cube.js 客户端,这样可以从服务器和可视化库中获取数据并进行显示。在本教程中,我们将使用 Recharts。Cube.js 是可视化不可知的,这意味着可以使用任何所需的库。我们还将使用 moment 和 numeral 来很好地格式化日期和数字。
![40f9f15067163665d5fc0e8a12ab09ce.png](https://i-blog.csdnimg.cn/blog_migrate/70d0bd217f2f65b5fdf544d6ce7cca90.jpeg)
这样,我们搞定了依赖关系。接下来继续创建我们的第一个图表,用以下替换 src/App.js 的内容:
import React, { Component } from "react";import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer} from "recharts";import cubejs from "@cubejs-client/core";import moment from "moment";import { QueryRenderer } from "@cubejs-client/react"; const cubejsApi = cubejs(process.env.REACT_APP_CUBEJS_TOKEN, { apiUrl: process.env.REACT_APP_API_URL}); const dateFormatter = item => moment(item).format("MMM YY"); class App extends Component { render() { return (