N8N中文教程
使用 n8n/Getting_started/Text_courses/Level_two

理解数据结构#

在本章中,你将学习 n8n 的数据结构,以及如何使用 Code 节点 来转换数据并模拟节点输出。

n8n 的数据结构#

从基本层面来说,n8n 节点的功能类似于一个提取、转换、加载(Extract, Transform, Load,简称 ETL)工具。这些节点允许你从多个不同的来源获取(提取)数据,以特定方式修改(转换)这些数据,并将其传递(加载)到目标位置。

在工作流中从一个节点传递到另一个节点的数据,必须采用一种能够被每个节点识别和解析的格式(结构)。在 n8n 中,这种所需的结构是一个对象数组(array of objects)。

关于对象数组

数组(Array)是一组值的列表。数组可以为空,也可以包含多个元素。每个元素存储在列表中的某个位置(索引),索引从 0 开始,并可通过索引编号进行引用。例如,在数组 ["Leonardo", "Michelangelo", "Donatello", "Raphael"] 中,元素 Donatello 存储在索引 2 的位置。

对象(Object)则以键值对(key-value pairs)的形式存储数据,而不是像数组那样通过数字索引存储值。键值对的顺序不重要,因为可以通过键名来访问对应的值。例如,以下对象包含两个属性(namecolor):

{
  name: 'Michelangelo',
  color: 'blue',
}

对象数组(Array of objects)是指包含一个或多个对象的数组。例如,下面的数组 turtles 包含四个对象:

const turtles = [
  {
    name: 'Michelangelo',
    color: 'orange',
  },
  {
    name: 'Donatello',
    color: 'purple',
  },
  {
    name: 'Raphael',
    color: 'red',
  },
  {
    name: 'Leonardo',
    color: 'blue',
  }
]

---|---
可以使用点符号语法 `object.property` 来访问对象的属性。例如,`turtles[1].color` 获取第二个 turtle 的颜色。
从一个节点发送到另一个节点的数据是以 JSON 对象数组的形式传输的。该集合中的元素称为 items(项目)。
[](https://docs.n8n.io/_images/courses/level-two/chapter-one/explanation_items.png)_Items(项目)_
n8n 节点会对输入数据中的每个 item 执行其操作。
[](https://docs.n8n.io/_images/flow-logic/looping/customer_datastore_node.png)_Customer Datastore 节点中的 Items(项目)_
## 使用 Code 节点创建数据集#
现在你已经熟悉了 n8n 的数据结构,可以利用它来创建自己的数据集或模拟节点输出。为此,使用 Code 节点 编写 JavaScript 代码,定义具有以下结构的对象数组:

1 2 3 4 5 6 7

| ```
return[
{
json:{
apple:'beets',
}
}
];

---|---
例如,在代码节点(Code node)中,表示忍者神龟的数组对象将如下所示:
[](https://docs.n8n.io/_images/courses/level-two/chapter-one/exercise_function_notnested.png)_代码节点中的对象数组_

### JSON 对象
请注意,该对象数组包含一个额外的键:`json`。n8n 要求你将每个对象包装在一个以 `json` 为键的对象中。

[](https://docs.n8n.io/_images/courses/level-two/chapter-one/explanation_datastructure.png)_n8n 中数据结构示意图_

最佳实践是按照 n8n 所需的正确结构传递数据。但如果你忘记为某项添加 `json` 键也不用担心,n8n(版本 0.166.0 及以上)会自动为你添加。

你也可以使用嵌套的键值对,例如当你需要定义主色和辅色时。在这种情况下,你需要用花括号 `{}` 将这些键值对进一步包裹起来。

### n8n 数据结构视频
这个演讲 对 n8n 中的数据结构提供了更详细的解释。

### 练习 #
在代码节点(Code node)中创建一个名为 `myContacts` 的对象数组,包含 `name` 和 `email` 属性,并且 `email` 属性进一步分为 `personal` 和 `work`。

显示答案

在 **代码节点** 的 JavaScript 代码字段中,你需要编写以下代码:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

| ```
var myContacts = [
{
json: {
name: 'Alice',
email: {
personal: 'alice@home.com',
work: 'alice@wonderland.org'
},
}
},
{
json: {
name: 'Bob',
email: {
personal: 'bob@mail.com',
work: 'contact@thebuilder.com'
},
}
},
];

return myContacts;

---|---
当你执行 **Code 节点** 时,结果应如下所示:
[](https://docs.n8n.io/_images/courses/level-two/chapter-one/exercise_function.png)_Code 节点的执行结果_
## 使用 Code 节点引用节点数据#
就像你可以使用 表达式(expressions) 来引用其他节点的数据一样,你也可以在 **Code 节点** 中使用一些 方法和变量(methods and variables)。
请确保在继续下一个练习之前阅读这些页面内容。
### 练习#
让我们基于上一个练习继续操作。在之前的练习中,你使用了 Code 节点创建了一个包含两个联系人及其姓名和邮箱的数据集。现在,将第二个 Code 节点连接到第一个节点上。在新的节点中,编写代码以创建一个名为 `workEmail` 的新字段,该字段引用第一位联系人的工作邮箱。
显示答案
在 **Code 节点** 的 JavaScript 代码字段中,你需要输入以下代码:

1 2 3

| ```
let items = $input.all();
items[0].json.workEmail = items[0].json.email['work'];
return items;

---|--- 当你执行 Code 节点 时,结果应如下所示: Code 节点引用结果

数据转换#

某些节点传入的数据结构可能与 n8n 所使用的格式不同。在这种情况下,你需要对数据进行 转换(transforming the data),以便每个项目可以被单独处理。 最常见的两种数据转换操作是:

  • 将单个项目拆分为多个项目
  • 将多个项目合并为单个项目

有多种方法可以实现上述目的的数据转换:

  * 使用 n8n 的 数据转换节点。这些节点可用于修改包含列表(数组)的输入数据结构,而无需在 **Code 节点** 中使用 JavaScript 代码:
    * 使用 **Split Out 节点** 将包含列表的单个数据项拆分为多个独立项。
    * 使用 **Aggregate 节点** 将多个独立项或其部分内容组合成新的单个项。

  * 使用 **Code 节点** 编写 JavaScript 函数,在 **Run Once for All Items** 模式下修改输入数据的结构:
    * 要从单个项创建多个项,可以使用如下 JavaScript 代码。此示例假设输入项中有一个名为 `data` 的键,其值为一个对象数组,格式为:`[{ "data": [{<item_1>}, {<item_2>}, ...] }]`:

1 2 3 4 5

| ```
return $input.first().json.data.map(item => {
  return {
    json: item
  };
});

---|--- * 要从多个项创建单个项,可以使用以下 JavaScript 代码:

1
2
3
4
5
6
7

| ``` return [ { json: { data_object: $input.all().map(item => item.json) } } ];


---|---

这些 JavaScript 示例假设你的整个输入数据就是你想要转换的内容。与上面的练习类似,你也可以通过指定具体字段来对特定字段执行任一操作。例如,如果我们的 `workEmail` 示例中某个字段包含了多个邮箱地址,我们可以运行如下代码:

1 2 3 4 5 6

| ```
let items = $input.all();
return items[0].json.workEmail.map(item => {
  return {
    json: item
  };
});

---|---

练习

  1. 使用 HTTP Request 节点 向 PokéAPI 发起 GET 请求:https://pokeapi.co/api/v2/pokemon。(该 API 无需认证)
  2. 使用 Split Out 节点results 字段中的数据进行转换。
  3. 使用 Code 节点results 字段中的数据进行转换。

显示解决方案

  1. 要从 PokéAPI 获取宝可梦数据,请使用以下参数执行 HTTP Request 节点

  2. 要使用 Split Out 节点 转换数据,请将该节点连接到 HTTP Request 节点,并设置以下参数:

    • Field To Split Out(要拆分的字段) :results
    • Include(包含) :No Other Fields(不包含其他字段)
  3. 要使用 Code 节点 转换数据,请将该节点连接到 HTTP Request 节点,并在 JavaScript Code(JavaScript 代码)字段中编写以下代码:

1
2
3
4
5
6

| ``` let items = $input.all(); return items[0].json.results.map(item => { return { json: item }; });


---|---