跳到主要内容

理解数据结构#

本章将介绍n8n的数据结构,以及如何使用代码节点进行数据转换和模拟节点输出。

n8n的数据结构#

本质上,n8n节点充当着提取、转换、加载(ETL)工具的角色。这些节点支持您从多个不同来源访问(提取)数据,以特定方式修改(转换)数据,并传递(加载)到目标位置。

在工作流中节点间传递的数据必须采用可被每个节点识别和解析的格式(结构)。在n8n中,这种必需结构是对象数组。

关于对象数组

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

对象存储的是键值对,而非像数组那样按数字索引存储值。键值对的顺序并不重要,因为可以通过引用键名来访问值。例如以下对象包含两个属性(namecolor):

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

对象数组是包含一个或多个对象的数组。例如,下面的 turtles 数组包含四个对象:

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

您可以使用点符号语法 object.property 访问对象的属性。例如,turtles[1].color 可获取第二个乌龟的颜色。

从一个节点发送到另一个节点的数据以 JSON 对象数组的形式传输。该集合中的元素称为数据项。

数据项

n8n 节点会对输入数据的每个数据项执行其操作。

客户数据存储节点中的数据项

使用代码节点创建数据集#

熟悉 n8n 数据结构后,您即可用它创建自己的数据集或模拟节点输出。通过使用代码节点编写 JavaScript 代码,您可以定义具有以下结构的对象数组:

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

例如,代表忍者神龟的对象数组在代码节点中会呈现如下形式:

代码节点中的对象数组

JSON对象

请注意该对象数组包含一个额外键:json。n8n要求将数组中的每个对象用另一个包含json键的对象进行包装。

n8n数据结构示意图

遵循n8n使用的正确数据结构来传递数据是良好实践。但若忘记为某个条目添加json键也无需担心,n8n(0.166.0及以上版本)会自动添加该键。

您还可以使用嵌套键值对,例如需要定义主色和辅助色时。这种情况下,需要将键值对进一步用花括号{}包裹。

n8n数据结构视频

本次讲座对n8n数据结构进行了更详细的说明。

练习#

在代码节点中创建名为myContacts的对象数组,需包含nameemail属性,且email属性需进一步拆分为personalwork

显示参考答案

代码节点的JavaScript代码编辑区中,您需要编写以下代码:

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;

当您执行代码节点时,结果应如下所示:

代码节点运行结果

通过代码节点引用节点数据#

正如您可以使用表达式引用其他节点的数据,您同样可以在代码节点中使用某些方法和变量

请确保在继续下一个练习前已阅读这些页面。

练习#

让我们基于前一个练习进行扩展——您之前使用代码节点创建了包含两个联系人姓名和邮箱的数据集。现在将第二个代码节点连接到第一个节点。在新节点中编写代码,创建名为workEmail的新列,用于引用第一个联系人的工作邮箱。

显示参考答案

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

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

当您执行代码节点时,结果应如下图所示:

代码节点参考

数据转换#

某些节点传入的数据结构可能与n8n中使用的数据结构不同。此时您需要通过数据转换操作,使每个数据项都能被独立处理。

数据转换中最常见的两种操作是:

  • 从单个数据项创建多个数据项
  • 从多个数据项创建单个数据项

针对上述需求,可通过以下方式实现数据转换:

  • 使用n8n的数据转换节点。这些节点可修改包含列表(数组)的传入数据结构,无需在代码节点中使用JavaScript代码:
    • 使用拆分节点将包含列表的单个数据项拆分为多个独立项
    • 使用聚合节点将分散的数据项或其部分内容分组合并为独立项
  • 使用代码节点编写JavaScript函数,通过对所有项运行一次模式修改传入数据的结构:
    • 若要从单个数据项创建多个项,可使用如下JavaScript代码。此示例假设数据项包含名为data的键,其值为数组格式:[{ "data": [{<项_1>}, {<项_2>}, ...] }]

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

要从多个项目创建单个项目,您可以使用以下JavaScript代码:

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

这些JavaScript示例假设您的全部输入即为需要转换的内容。如上文练习所示,您也可以针对特定字段执行任一操作,只需在项目列表中标识该字段即可。例如,假设我们的workEmail示例在单个字段中包含多个电子邮件地址,则可以运行如下代码:

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

练习#

  1. 使用 HTTP请求节点 向 PokéAPI https://pokeapi.co/api/v2/pokemon 发起GET请求(此接口无需身份验证)
  2. 使用 拆分输出节点 转换 results 字段中的数据
  3. 使用 代码节点 转换 results 字段中的数据

查看解决方案

  1. 要从 PokéAPI 获取宝可梦数据,请使用以下参数执行 HTTP请求节点
  2. 要使用 拆分输出节点 转换数据,请将该节点连接到 HTTP请求节点 并设置以下参数:
    • 待拆分字段:results
    • 包含:无其他字段
  3. 要使用 代码节点 转换数据,请将该节点连接到 HTTP请求节点 并在JavaScript代码字段中写入以下代码:
let items = $input.all();
return items[0].json.workEmail.map(item => {
return {
json: item
}
});