# 3. 创建数据模型

本节将介绍数据建模的核心概念，帮助您掌握如何使用 Recurve 创建一个简单的数据转换用例。

## Recurve 中的资产

在 Recurve 中，资产是构建数据工作流的核心要素。可以将其视为数据转换过程中创建和管理的关键组件，每种资产类型都发挥着特定作用，共同作用将原始数据转化为有价值的洞察。

在 **数据建模** 中，主要使用以下几类资产：

* **数据源（Sources）：** 指向原始数据，便于连接并记录数据的来源。
* **模型（Models）：**&#x5904;理数据的查询，通过转换生成结构化的、适合分析的数据集。
* **Jinja 宏和变量（Jinja macros and variables）：**&#x4A;inja 模板工具，为 SQL 添加编程逻辑，使转换过程更具动态性和可维护性。

## 数据建模流程

Recurve 的数据建模流程遵循逻辑步骤，帮助您构建和验证转换工作流。

1. **定义源数据：**&#x9996;先定义代表原始数据表的源数据，便于描述和记录数据的来源。
2. **创建数据模型：**&#x5728;源数据基础上创建数据模型，将原始数据转化为有用的分析数据集。每个模型表示一个特定的转换步骤，并逐步构建。
3. **配置物化方式：**&#x6307;定模型结果在数据仓库中的物化方式。
4. **添加数据测试：**&#x4E3A;模型添加数据测试，以确保其正确运行。每次模型成功构建后，这些测试会自动执行。

建议在开发周期中包含以上步骤，以确保转换在应用到生产数据之前正常运行。

## 前提条件

以下操作示例使用由 dbt 社区提供的  `jaffle_shop` 数据集（一个虚构的电商商店）。您可以按照该仓库中的指南生成数据并将其加载到目标数据库： [jaffle-shop-generator](https://github.com/dbt-labs/jaffle-shop-generator)。

## 操作流程

让我们通过实际步骤体验 Recurve 的数据建模流程。

首先，在 **数据开发/  Data development** 仪表板中打开您创建的项目。默认情况下，Recurve 将导航&#x81F3;**“设计/ Design”**&#x90E8;分，在这里完成所有转换活动。

<figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2F4KEwhUWJNrvZ7NWdtrSj%2FRecurve_project_data_section.png?alt=media&#x26;token=45a8d941-c6c2-4710-817e-293f30f61ef3" alt=""><figcaption></figcaption></figure>

### 定义源数据

请按照以下步骤操作：

1. &#x5728;**“模型/ Models ”**&#x9009;项卡中，点&#x51FB;**“+”**&#x56FE;标并选&#x62E9;**“添加源/ Add source”**。
2. 在打开的窗口中：
   1. 选择连接类型。
   2. 选择目标连接，即您在 [2.-chuang-jian-xiang-mu](https://docs.reorc.com/cn-reorc-help-center/kuai-su-kai-shi/2.-chuang-jian-xiang-mu "mention") 中已设置好的连接。
3. 点&#x51FB;**“下一步/ Next”**&#x540E;，Recurve 将显示目标连接中所有可用的表。

<figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FQPXm5cmfkbBrV0IIQ19K%2FRecurve_add_source_select_tables.png?alt=media&#x26;token=fa86f5d7-db16-4ab6-9f24-9c52408639ec" alt=""><figcaption><p>从连接中选择表</p></figcaption></figure>

4. 选择所需的原始表或模型。

   在此示例中，我们选择 `jaffle_shop` 架构下的所有表。

<details>

<summary>jaffle_shop 数据集所含表</summary>

`jaffle_shop` 架构包含以下表：

* Customers：下订单的客户
* Orders：由客户发起的订单
* Products：订单中包含的食品和饮料
* Items：属于产品的订单项
* Supplies：生产产品所需的原材料
* Stores：订单下单和履行的门店

</details>

5. 点&#x51FB;**“添加源/ Add source”**。

选定的表将被添加&#x5230;**“数据源/ Sources”**&#x6587;件夹中，并按架构名称分组。

<figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FnrOEvNmMCgsyH4V6rz6l%2FRecurve_added_sources.png?alt=media&#x26;token=a0383586-6c9a-4830-86df-aa3fd8da878a" alt=""><figcaption></figcaption></figure>

### 创建数据模型

为了展示数据模型的动态性和模块化，我们将创建三个模型：

{% tabs %}
{% tab title="stg\_customers" %}
此暂存模型（ Stage model ）通过从原始客户表`customers`中选择相关字段（如`customer_id`，`customer_name`）来标准化客户数据。

此过程使用 Jinja 的  [`{{ source() }}`](https://docs.reorc.com/cn-reorc-help-center/advanced_usage/jinja-mu-ban) 函数来引用前一部分中定义的原始表。

```sql
SELECT
  id AS customer_id,
  name AS customer_name
FROM
  {{ source('jaffle-shop', 'raw_customers') }}
```

{% endtab %}

{% tab title="stg\_orders" %}
与 `stg_customers`类似，此暂存模型通过从原始订单表`orders` 中选择并重命名相关字段 （`order_id`、`customer_id`、 `order_date`等） 来标准化订单数据。

```sql
SELECT
  id AS order_id,
  store_id AS location_id,
  customer AS customer_id,
  subtotal AS subtotal_cents,
  tax_paid AS tax_paid_cents,
  order_total AS order_total_cents,
  ordered_at
FROM
  {{ source('jaffle-shop', 'raw_orders') }}
```

{% endtab %}

{% tab title="customers" %}
此模型将客户数据与订单历史整合在一起。

在这里，我们使用 [`{{ ref() }}`](https://docs.reorc.com/cn-reorc-help-center/advanced_usage/jinja-mu-ban) 函数引用这两个暂存模型。

{% code overflow="wrap" %}

```sql
-- Reference the staged data (stg_customers and stg_orders) to gather customer information.
WITH
  customers AS (
    SELECT
      *
    FROM
      {{ ref('stg_customers') }}
  ),
  orders AS (
    SELECT
      *
    FROM
      {{ ref('stg_orders') }}
  ),
  -- Aggregate the order data to calculate metrics per customer
  customer_orders AS (
    SELECT
      customer_id,
      min(ordered_at) AS first_order_time,
      max(ordered_at) AS most_recent_order_time,
      count(order_id) AS number_of_orders
    FROM
      orders
    GROUP BY
      1
  ),
  -- Join aggregated data with the customer information to produce details about each customer and their order history
  final AS (
    SELECT
      customers.customer_id,
      customers.customer_name,
      customer_orders.first_order_time,
      customer_orders.most_recent_order_time,
      coalesce(customer_orders.number_of_orders, 0) AS number_of_orders
    FROM
      customers
      LEFT JOIN customer_orders USING (customer_id)
  )
SELECT
  *
FROM
  final
```

{% endcode %}
{% endtab %}
{% endtabs %}

按照以下步骤创建每个模型：

1. &#x5728;**“模型/ Models”**&#x9009;项卡中，点&#x51FB;**“+”**&#x56FE;标并选&#x62E9;**“新建 SQL 模型/ New SQL model”**。
2. 提供模型名称，然后点&#x51FB;**“创建/ Create”**。

   新模型将被放置&#x5728;**“模型/ Models”**&#x6587;件夹中。
3. 打开模型编辑器并粘贴查询。

   <figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FJxV4Jo2tcjx3g64Pe4av%2Fimage.png?alt=media&#x26;token=05b259b9-e2bf-4e11-b0d7-6e27f4ae718b" alt=""><figcaption></figcaption></figure>
4. 点&#x51FB;**“保存/ Save”**&#x786E;认更改。
5. 点&#x51FB;**“预览/ Preview”**&#x4EE5;查看查询输出，结果将&#x5728;**“结果/ Result”**&#x9009;项卡中显示。

   <figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FyLKCZmamYpuUPwqOx9ZF%2Fimage.png?alt=media&#x26;token=07ab58b0-d3d7-4097-82e9-095aaf8cdafa" alt=""><figcaption></figcaption></figure>
6. 请按照上述步骤创建其他两个模型。

现在，我们已经创建了两个标准化原始数据的暂存模型，以及一个汇总并整合结果的模型，可以&#x5728;**“数据血缘/ Data linage”**&#x4E2D;查看它们，以更好地理解它们之间的关系。

打开一个模型，并切换&#x5230;**“血缘视图/ Lineage view”**&#x9009;项。这将显示一个 DAG（有向无环图），展示从原始数据到最终下游模型的资产关系。

数据血缘是通过 `source()` 和`ref()` 函数实现的，这些函数会自动跟踪资产的依赖关系。

<figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FJZP54OsFLRgQisbIkRZP%2FRecurve_customers_data_lineage.png?alt=media&#x26;token=1143b577-724a-4b6e-81e7-fe7ffbdd6108" alt=""><figcaption></figcaption></figure>

### 配置物化方式

您可以具体配置模型在数据仓库中的物化方式。

默认情况下，所有模型的物化方式为 **表格/ table** 。

按照以下步骤操作：

1. 打开模型编辑器。
2. 点击 ![](https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FP7seWaftdZHu0p9KAoG2%2FRecurve_info_button.png?alt=media\&token=88910478-ad96-4afc-8fb1-33053088e1f1)图标。
3. &#x5728;**“物化方式/ Materialization”**&#x5B57;段中，选择所需的物化方式选项。

   <figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2Fs4VBDCfKoJ5d1hxtvyeU%2Fimage.png?alt=media&#x26;token=d62dbf91-dea5-4883-9db1-0f02a859e9b4" alt=""><figcaption></figcaption></figure>

继续使用我们的三个示例模型，我们可以将暂存模型物化为视图，以确保它们反映最新的源数据，并最大限度地减少存储成本。另一方面，汇总模型可以物化为表格，因为它是最终模型，且查询频率较高。

### 添加数据测试

{% hint style="info" %}
**即将上线:** 数据测试部分即将上线。
{% endhint %}

数据测试是简单的 SQL 查询，它根据您设置的条件返回失败的记录。这些测试用于验证转换后数据的正确性，确保模型的结果符合预定义的标准。

Recurve 提供了一系列内置测试，您可以快速将其添加到模型中。

按照以下步骤向模型添加测试：

1. 打开模型编辑器。

2. 切换&#x5230;**“测试用例/ Test cases”**&#x9009;项卡。

   <figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FtgXCBnVqKlGdFNLCo11K%2FRecurve_test_case_tab.png?alt=media&#x26;token=131350dc-e706-42df-9028-cf3416a75ab1" alt=""><figcaption></figcaption></figure>

3. 点击 **+ 添加新建/ + Add new**。

4. 选择一个模板并指定相应的值。

   例如，对于 `stg_orders` 模型，我们可以添加 "空值" 测试，以验证日期列中是否存在`null` 值。

   <figure><img src="https://3914025029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMNJfiu2Or0lnmkm2x228%2Fuploads%2FSCP4rCkzXN7KzWWW1CkQ%2FRecurve_empty_value_check_stg_orders.png?alt=media&#x26;token=07083849-38a2-495f-af38-7e75201310d4" alt=""><figcaption></figcaption></figure>

5. 点击 **添加/ Add。**

新的测试将被添加到模型的测试用例列表中，并将在每次模型在控制台运行或作为管道的一部分运行时自动执行。
