# 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="/files/6Nht3ryNYwo5w6XeZL4r" alt=""><figcaption></figcaption></figure>

### 定义源数据

请按照以下步骤操作：

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

<figure><img src="/files/0POYEIKmvIEKp2MByjLW" 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="/files/pOjnzJPMRA7gBGjMpiC3" alt=""><figcaption></figcaption></figure>

### 创建数据模型

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

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

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

```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() }}`](/cn-reorc-help-center/advanced_usage/jinja-mu-ban.md) 函数引用这两个暂存模型。

{% 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="/files/ygDgTFDvACv0zQTVtTPV" alt=""><figcaption></figcaption></figure>
4. 点&#x51FB;**“保存/ Save”**&#x786E;认更改。
5. 点&#x51FB;**“预览/ Preview”**&#x4EE5;查看查询输出，结果将&#x5728;**“结果/ Result”**&#x9009;项卡中显示。

   <figure><img src="/files/OfnWYOSKxJArV9XhvPPi" alt=""><figcaption></figcaption></figure>
6. 请按照上述步骤创建其他两个模型。

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

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

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

<figure><img src="/files/zLri0r6EZx3EBCHA2wVp" alt=""><figcaption></figcaption></figure>

### 配置物化方式

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

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

按照以下步骤操作：

1. 打开模型编辑器。
2. 点击 ![](/files/BwrkolFklOQtE4D9cBno)图标。
3. &#x5728;**“物化方式/ Materialization”**&#x5B57;段中，选择所需的物化方式选项。

   <figure><img src="/files/AMbLyxif1nq06Q3T763q" alt=""><figcaption></figcaption></figure>

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

### 添加数据测试

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

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

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

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

1. 打开模型编辑器。

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

   <figure><img src="/files/PfY4ELKX7PGjdKmXk9G4" alt=""><figcaption></figcaption></figure>

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

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

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

   <figure><img src="/files/rKNHMMVlraJ8a4a81DI0" alt=""><figcaption></figcaption></figure>

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.reorc.com/cn-reorc-help-center/kuai-su-kai-shi/3.-chuang-jian-shu-ju-mo-xing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
