第四章:数据与表达式:工作流的“血液”

如果说节点是工作流的“器官”,那么在节点之间流动的数据就是维持工作流生命的“血液”。理解 n8n 如何组织和处理数据,以及如何使用表达式来动态地引用和操作这些数据,是让你从“会用”n8n 到“用好”n8n 的关键一步。

### 4.1 理解 n8n 的数据结构

n8n 的内部数据流有一个核心原则:**所有数据都是一个由多个“数据项” (Items) 组成的数组。**

即使上一个节点只输出一个结果(比如 `HTTP Request` 节点获取到的单个 JSON 对象),在 n8n 内部,它也会被包装成一个只包含一个元素的数组。

每个数据项 (Item) 又包含两种主要数据类型:

* **JSON Data**: 这是最主要的数据类型,包含了结构化的键值对信息。我们之前看到的 `{“english”: “…”, “chinese”: “…”}` 就是 JSON 数据。
* **Binary Data**: 用于表示非文本内容,如图片、PDF 文件、视频等。每个数据项可以附带一个二进制文件。

理解“**一切皆为 Items 数组**”这个核心概念至关重要,它直接影响了我们后续如何引用数据。

### 4.2 表达式入门:`{{ }}` 的魔力

在 n8n 的几乎所有节点的参数设置框中,你都可以看到 `Add Expression` 的选项。表达式是 n8n 的一大核心特色,它允许你**动态地**从上游节点获取数据,而不是写死一个固定的值。

所有 n8n 表达式都必须写在双大括号 `{{ }}` 中。

例如,在 `Set` 节点中:

* `Value` 设置为 `Hello World` -> 输出永远是固定的字符串 “Hello World”。
* `Value` 设置为 `{{ $json.name }}` -> 输出会动态地变成上游节点传入的 `name` 字段的值。

### 4.3 核心表达式语法

要在表达式中准确地引用到你需要的数据,你需要掌握几个核心的“寻址”变量。

#### **`$json`**

* **含义**:代表**当前正在被处理的这一个数据项 (Item) 的 JSON 部分**。
* **用法**:`{{ $json.fieldName }}`
* **示例**:当 `Set` 节点处理一个数据项 `{“name”: “Alice”, “age”: 30}` 时,`{{ $json.name }}` 的结果就是 `Alice`。
* **注意**:这是**最常用**的变量,90% 的情况下你用的都是它。

#### **`$item(index)`**

* **含义**:一个函数,用于访问**当前批次**中**指定索引**的数据项。
* **用法**:`{{ $item(0).json.fieldName }}`
* **示例**:假设上一个节点输出了一个包含 3 个数据项的数组。在 `Set` 节点中,`{{ $item(0).json.name }}` 会获取**第一个**数据项的 `name` 字段。无论当前正在处理的是第几个数据项,这个表达式返回的永远是第一个数据项的值。
* **应用场景**:当你需要在一个数据项的处理逻辑中,引用到另一个数据项的值时。比如,在循环处理订单项时,需要引用订单头部的总信息。

#### **`$items(“NodeName”)`**

* **含义**:一个函数,用于获取**指定节点**的**所有输出数据项**(一个完整的数组)。
* **用法**:`{{ $items(“HTTP Request”)[0].json.fieldName }}`
* **示例**:`{{ $items(“获取所有用户”)[0].json.id }}` 会获取名为“获取所有用户”的那个节点输出的**第一个**用户的 ID。
* **应用场景**:当你在工作流的后面部分,需要回头引用很早之前某个节点的数据时,这个函数非常有用,可以避免数据流被后续节点污染或修改。

#### **`$node[“NodeName”].context`**

* **含义**:用于获取指定节点的上下文信息,而不是其输出数据。
* **用法**:`{{ $node[“My Cron”].context.runIndex }}`
* **`$runIndex`**:一个非常有用的上下文变量,代表当前工作流是第几次执行。它的值从 0 开始计数。
* **应用场景**:当你需要为每次执行生成一个唯一的标识符时,比如 `Invoice-{{ $runIndex }}` 会生成 `Invoice-0`, `Invoice-1` 等。

### 4.4 内置变量与 JavaScript 方法

除了引用数据,n8n 的表达式引擎还内置了一些方便的变量,并支持标准的 JavaScript 方法,让你可以直接在 `{{ }}` 中进行简单的数据处理。

#### **内置变量**

* `{{ $now }}`: 返回一个包含当前日期和时间的 Luxon DateTime 对象。你可以用它来获取各种时间格式,如 `{{ $now.toISODate() }}` -> `2024-05-22`。
* `{{ $today }}`: `{{ $now }}` 的简写形式,返回当天的开始时间。
* `{{ $workflow.id }}`: 当前工作流的 ID。
* `{{ $execution.id }}`: 当前这次执行的唯一 ID。

#### **常用的 JavaScript 方法**

* **字符串处理**:
* `{{ $json.name.toUpperCase() }}` -> 转为大写
* `{{ $json.email.split(‘@’)[0] }}` -> 分割字符串
* `{{ $json.notes.includes(‘urgent’) }}` -> 判断是否包含
* **数字计算**:
* `{{ $json.price * 1.2 }}` -> 基本运算
* `{{ parseFloat($json.price_str) }}` -> 字符串转数字
* **条件逻辑 (三元运算符)**:
* `{{ $json.score > 60 ? ‘Pass’ : ‘Fail’ }}` -> 如果分数大于60则为’Pass’,否则为’Fail’。
* **数组操作**:
* `{{ $items(“Read RSS”).length }}` -> 获取数组长度
* `{{ $json.tags.join(‘, ‘) }}` -> 将数组用逗号连接成字符串

### 4.5 实战演练:动态格式化 API 响应

回到我们第二章的“每日英语学习助手”案例。假设我们想生成的最终输出是一个 Markdown 格式的字符串,方便直接发布。

我们可以在 `Set` 节点之后再加一个 `Set` 节点,或者直接修改原来的 `Set` 节点。

1. 添加一个新的 `Value`。
2. **Name**: `markdown_output`
3. **Value**: 设置为表达式模式,并输入以下内容:

“`javascript
## {{ $json.english }}

> {{ $json.chinese }}

![Daily Image]({{ $json.image }})
“`

执行后,这个 `Set` 节点的输出就会有一个新的 `markdown_output` 字段,其内容是拼接好的、可以直接使用的 Markdown 文本。

通过本章的学习,你已经掌握了 n8n 中数据流动的规律和动态处理数据的核心武器——表达式。现在,你可以更加自如地驾驭你的数据,让它们按照你的意愿流动和变形。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容