首页
学习
活动
专区
圈层
工具
发布

n8n 核心概念深度解析:节点、表达式与数据流

写在前面

前两篇文章,咱们把 n8n 跑起来了,也做了一些简单的工作流。

从零搭建 n8n 开发环境:Docker 部署完全指南

但你可能会发现,遇到稍微复杂点的场景就不知道怎么处理了。

• 怎么从 API 返回的复杂 JSON 中提取想要的数据?

• 如何处理数组和循环?

• 表达式{{ }}里能写什么,不能写什么?

• 节点之间数据是怎么传递的?

这些问题,都是因为对 n8n 的核心概念理解不够深入。今天这篇文章,我会用大白话把这些概念讲透,让你彻底理解 n8n 的运行机制。

理解 n8n 的数据模型

先从最底层的数据结构说起。

n8n 的数据格式

n8n 内部用JSON 数组来传递数据,格式是这样的:

[

{

  "json": {

    "name": "张三",

    "age": 25

  },

  "binary": {},

  "pairedItem": 0

}

]

关键字段:

json:实际的数据内容

binary:二进制数据(文件、图片等)

pairedItem:追踪数据来源

这个格式看起来有点啰嗦,但有它的道理:每个节点都能处理多条数据

为什么是数组?

假设你要批量处理 100 个用户的数据,n8n 是这样处理的:

[

{ "json": { "name": "用户1", "age": 20 } },

{ "json": { "name": "用户2", "age": 30 } },

{ "json": { "name": "用户3", "age": 40 } },

...

]

一次性传递,一次性处理。这就是 n8n 高效的原因。

数据传递规则

节点A(输出3条数据) 节点B(输入3条,输出3条) 节点C(输入3条)

一对一:每条输入对应一条输出

多对一:多条输入合并成一条输出(如聚合)

一对多:一条输入拆分成多条输出(如分割)

节点详解

1. 触发节点(Trigger Nodes)

触发节点是工作流的起点,监听事件或条件。

Schedule Trigger - 定时触发

# 每小时执行

Hours Interval: 1

# 每天特定时间

Cron Expression: 0 9 * * *  # 每天 9 点

# 每周一执行

Cron Expression: 0 9 * * 1

Cron 表达式速查

┌───────────── 分钟 (0 - 59)

│ ┌───────────── 小时 (0 - 23)

│ │ ┌───────────── 日期 (1 - 31)

│ │ │ ┌───────────── 月份 (1 - 12)

│ │ │ │ ┌───────────── 星期 (0 - 6,0 是周日)

│ │ │ │ │

* * * * *

常用例子:

•0 * * * *- 每小时整点

•0 9,12,18 * * *- 每天 9 点、12 点、18 点

•*/15 * * * *- 每 15 分钟

•0 0 1 * *- 每月 1 号凌晨

Webhook Trigger - HTTP 触发

HTTP Method: POST

Path: my-webhook

Authentication: Header Auth

Header Name: X-API-Key

Header Value: {{ $credentials.apiKey }}

访问地址:https://n8n.yourdomain.com/webhook/my-webhook

应用场景

• 接收第三方服务的回调(支付成功、订单状态变更)

• 前端调用触发工作流

• 其他系统集成

Manual Trigger - 手动触发

用于测试,点击按钮执行。生产环境要删掉,换成真正的触发器。

2. 常规节点(Regular Nodes)

HTTP Request - 最常用的节点

发起 HTTP 请求,调用任意 API。

GET 请求

Method: GET

URL: https://api.example.com/users/{{ $json.userId }}

Authentication: Header Auth

Headers:

Authorization: Bearer {{ $credentials.token }}

POST 请求

Method: POST

URL: https://api.example.com/users

Body Content Type: JSON

Body:

{

  "name": "{{ $json.name }}",

  "email": "{{ $json.email }}"

}

处理分页

# 配合 Loop Over Items 节点

URL: https://api.example.com/users?page={{ $json.page }}&size=100Function - JavaScript 处理

最灵活的节点,可以写任意 JavaScript 代码。

基础用法

// 处理单条数据

const item = $input.item.json;

return {

fullName: `${item.firstName} ${item.lastName}`,

age: 2025 - item.birthYear,

isAdult: (2025 - item.birthYear) >= 18

};

处理多条数据

// 遍历所有输入数据

const items = $input.all();

return items.map(item => ({

json: {

  userId: item.json.id,

  userName: item.json.name.toUpperCase(),

  createdAt: new Date().toISOString()

}

}));

引入 npm 包

// 先在 Function 节点中安装

const moment = require('moment');

return {

formattedDate: moment().format('YYYY-MM-DD'),

timestamp: moment().unix()

};Code - Python 处理

n8n 也支持 Python(需要配置 Python 环境)。

# 处理数据

import json

from datetime import datetime

items = _input.all()

results = []

for item in items:

  data = item.json

  results.append({

      'json': {

          'name': data['name'],

          'processed_at': datetime.now().isoformat(),

          'length': len(data['content'])

      }

  })

return resultsIF - 条件判断

简单条件

Value 1: {{ $json.age }}

Operation: Larger Than

Value 2: 18

多个条件

Conditions:

- {{ $json.age }} > 18

- {{ $json.country }} = "China"

Combine: AND  # 或者 OR

复杂判断

// 用 Function 节点更灵活

const item = $input.item.json;

if (item.age >= 18 && item.status === 'active') {

return { route: 'true' };

} else {

return { route: 'false' };

}Switch - 多路分支

比 IF 节点更强大,支持多个分支。

Mode: Rules

Rules:

- {{ $json.status }} equals "pending"  输出1

- {{ $json.status }} equals "approved"  输出2

- {{ $json.status }} equals "rejected"  输出3

Fallback: 输出4(都不匹配)Merge - 合并数据

合并多个节点的输出。

模式一:Append(追加)

节点A: [1, 2, 3]

节点B: [4, 5, 6]

合并后: [1, 2, 3, 4, 5, 6]

模式二:Keep Matches(保留匹配)

Join: $json.userId  # 根据 userId 匹配

Mode: Keep Matches

节点A: [{userId: 1, name: "张三"}]

节点B: [{userId: 1, age: 25}]

合并后: [{userId: 1, name: "张三", age: 25}]Loop Over Items - 循环处理

处理数组数据,逐个执行。

Input: {{ $json.userIds }}  # [1, 2, 3, 4, 5]

Batch Size: 1

# 会循环5次,每次处理一个 userId

配合 HTTP Request 批量调用 API:

Loop HTTP Request (获取用户详情) 收集结果3. 数据转换节点Set - 设置数据

修改数据结构,最常用的节点之一。

保留模式(Keep)

Mode: Keep Only Set

Values to Set:

- Name: userId

  Value: {{ $json.id }}

- Name: userName

  Value: {{ $json.profile.name }}

输入:

{ "id": 123, "profile": { "name": "张三", "age": 25 }, "other": "..." }

输出:

{ "userId": 123, "userName": "张三" }

手动模式(Manual)

Mode: Manual Mapping

Mapping:

user:

  id: {{ $json.id }}

  name: {{ $json.name }}

  createdAt: {{ $now.toISO() }}Item Lists - 数组操作

拆分数组

Operation: Split Out Items

Field: {{ $json.users }}  # 数组字段

输入:

{ "users": [{ "name": "张三" }, { "name": "李四" }] }

输出:

[

{ "name": "张三" },

{ "name": "李四" }

]

聚合数组

Operation: Aggregate Items

Aggregate: All Items

Output Format: Array

Field Name: results

输入:

[

{ "score": 80 },

{ "score": 90 }

]

输出:

{ "results": [{ "score": 80 }, { "score": 90 }] }Edit Fields - 字段操作

Operations:

- Rename: oldName  newName

- Remove: fieldToDelete

- Convert: age  Number表达式深度解析

表达式是 n8n 的核心,用{{ }}包裹。

1. 基础语法

引用数据

// 上一个节点的数据

{{ $json.fieldName }}

// 指定节点的数据

{{ $('节点名称').item.json.fieldName }}

// 当前时间

{{ $now }}

// 当前工作流 ID

{{ $workflow.id }}

// 执行 ID

{{ $execution.id }}数组和对象

// 数组第一个元素

{{ $json.users[0].name }}

// 对象嵌套

{{ $json.data.user.profile.email }}

// 数组长度

{{ $json.users.length }}

// 遍历数组

{{ $json.users.map(u => u.name).join(', ') }}2. 内置函数字符串处理

// 转大写

{{ $json.name.toUpperCase() }}

// 截取

{{ $json.text.substring(0, 10) }}

// 替换

{{ $json.content.replace('旧词', '新词') }}

// 分割

{{ $json.tags.split(',') }}

// 去除空格

{{ $json.input.trim() }}时间处理

// 当前时间(ISO 格式)

{{ $now.toISO() }}

// 格式化时间(注意:n8n 使用 Luxon,用小写 yyyy)

{{ $now.toFormat('yyyy-MM-dd HH:mm:ss') }}

// 其他常用格式

{{ $now.toFormat('yyyy-MM-dd') }}  // 只要日期

{{ $now.toFormat('HH:mm:ss') }}    // 只要时间

{{ $now.toFormat('yyyy年MM月dd日') }}  // 中文格式

// 时间计算

{{ $now.plus({ days: 7 }).toISO() }}  // 7天后

{{ $now.minus({ hours: 1 }).toISO() }} // 1小时前

// 时间戳

{{ $now.toMillis() }}  // 毫秒

{{ $now.toSeconds() }}  // 秒数学计算

// 基本运算

{{ $json.price * 0.8 }}  // 打8折

{{ $json.total + $json.tax }}  // 求和

{{ Math.round($json.value) }}  // 四舍五入

{{ Math.max($json.a, $json.b) }}  // 最大值条件判断

// 三元运算

{{ $json.age >= 18 ? '成年' : '未成年' }}

// 多重判断

{{ $json.score >= 90 ? '优秀' : $json.score >= 60 ? '及格' : '不及格' }}

// 空值处理

{{ $json.name || '未命名' }}

{{ $json.value ?? 0 }}  // null/undefined 时返回 0数组操作

// 映射

{{ $json.users.map(u => u.name) }}

// 过滤

{{ $json.users.filter(u => u.age > 18) }}

// 查找

{{ $json.users.find(u => u.id === 123) }}

// 累加

{{ $json.numbers.reduce((sum, n) => sum + n, 0) }}

// 排序

{{ $json.items.sort((a, b) => b.price - a.price) }}3. 高级技巧动态字段名

// 根据条件选择字段

{{ $json[$json.fieldType] }}

// 例如:fieldType = "name",则获取 $json.nameJSON 序列化

// 对象转字符串

{{ JSON.stringify($json) }}

// 字符串转对象

{{ JSON.parse($json.jsonString) }}正则表达式

// 提取邮箱

{{ $json.text.match(/[\w.-]+@[\w.-]+\.\w+/)[0] }}

// 提取数字

{{ $json.text.match(/\d+/g) }}

// 替换(正则)

{{ $json.text.replace(/\s+/g, '-') }}  // 空格替换为横杠错误处理

// try-catch(在 Function 节点中)

try {

return JSON.parse($json.data);

} catch (error) {

return { error: error.message };

}数据流转实战案例1:处理复杂 JSON

API 返回:

{

"code": 0,

"data": {

  "list": [

    { "id": 1, "name": "商品A", "price": 99.9 },

    { "id": 2, "name": "商品B", "price": 199.9 }

  ],

  "total": 2

}

}

提取商品列表

方式一:用 Set 节点

Mode: Keep Only Set

Values:

- Name: products

  Value: {{ $json.data.list }}

方式二:用 Function 节点

return $input.item.json.data.list.map(item => ({

json: {

  productId: item.id,

  productName: item.name,

  price: item.price

}

}));案例2:批量 API 调用

需求:有 100 个用户 ID,批量获取用户详情。

工作流设计:

1. [Set] 设置用户 ID 列表

  2. [Split In Batches] 每次处理 10 个

  3. [HTTP Request] 调用 API

  4. [Wait] 等待 1 秒(避免限流)

  5. [循环] 返回步骤 2

  6. [Merge] 合并所有结果

Split In Batches 配置

Batch Size: 10

Options:

- Reset: false

HTTP Request 配置

Method: GET

URL: https://api.example.com/users/{{ $json.userId }}案例3:数据去重

输入:

[

{ "userId": 1, "name": "张三" },

{ "userId": 2, "name": "李四" },

{ "userId": 1, "name": "张三" }  // 重复

]

用 Function 节点去重:

const items = $input.all();

const seen = new Set();

const unique = [];

for (const item of items) {

const key = item.json.userId;

if (!seen.has(key)) {

  seen.add(key);

  unique.push(item);

}

}

return unique;案例4:数据聚合统计

输入:订单列表

[

{ "userId": 1, "amount": 100 },

{ "userId": 1, "amount": 200 },

{ "userId": 2, "amount": 150 }

]

统计每个用户的总消费:

const items = $input.all();

const stats = {};

for (const item of items) {

const userId = item.json.userId;

const amount = item.json.amount;

if (!stats[userId]) {

  stats[userId] = { userId, totalAmount: 0, orderCount: 0 };

}

stats[userId].totalAmount += amount;

stats[userId].orderCount += 1;

}

return Object.values(stats).map(stat => ({ json: stat }));

输出:

[

{ "userId": 1, "totalAmount": 300, "orderCount": 2 },

{ "userId": 2, "totalAmount": 150, "orderCount": 1 }

]调试技巧1. 查看中间数据

在关键节点后加Set节点,输出数据看看:

Mode: Keep Only Set

Values:

- Name: debug

  Value: {{ $json }}2. 使用 Function 节点打印

console.log('当前数据:', $input.item.json);

return $input.item.json;

然后在执行历史里查看控制台输出。

3. 拆分复杂表达式

表达式太复杂,容易出错。拆成多个步骤:

// 不好:一行搞定

{{ $json.users.filter(u => u.age > 18).map(u => u.name).join(', ') }}

// 好:分步处理

// 步骤1:Set 节点过滤

{{ $json.users.filter(u => u.age > 18) }}

// 步骤2:Set 节点提取名字

{{ $json.map(u => u.name) }}

// 步骤3:Set 节点拼接

{{ $json.join(', ') }}4. 错误节点

在工作流末尾加一个Error Trigger节点,捕获错误并发送通知:

[任意节点出错] [Error Trigger] [发送告警]性能优化建议1. 避免不必要的节点

不好:

HTTP Request Set Set Set IF ...

好:

HTTP Request Function(一次性处理完) IF ...2. 批量处理

不好:逐个调用 API(100次请求)

Loop HTTP Request

好:批量调用(1次请求)

HTTP Request (Body: { "ids": [1,2,3,...] })3. 减少数据传输

不好:传递完整数据

{{ $json }}  // 包含很多无用字段

好:只传递需要的字段

{{ { id: $json.id, name: $json.name } }}4. 合理使用缓存

对于不常变化的数据,可以缓存到全局变量:

// 读取缓存

const cache = $workflow.staticData.cache || {};

// 检查缓存

if (cache[key]) {

return cache[key];

}

// 调用 API 并缓存

const result = await fetchData();

$workflow.staticData.cache = cache;

cache[key] = result;

return result;总结

今天咱们深入学习了:

1.数据模型:n8n 的数据结构和传递机制

2.节点详解:触发节点、常规节点、数据转换节点

3.表达式:基础语法、内置函数、高级技巧

4.数据流转:复杂 JSON 处理、批量调用、去重、聚合

5.调试技巧:查看中间数据、拆分表达式、错误捕获

6.性能优化:减少节点、批量处理、合理缓存

理解了这些概念,你就能设计出高效、优雅的工作流。

下一篇,咱们进入实战阶段:HTTP 节点深度使用,打造你的数据采集器,学习各种 API 调用技巧和反爬虫应对策略。

延伸阅读

• n8n 表达式官方文档[1]

• JavaScript MDN 文档[2]

• Luxon 时间库文档[3]

引用链接

[1]n8n 表达式官方文档:https://docs.n8n.io/code/expressions/

[2]JavaScript MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript

[3]Luxon 时间库文档:https://moment.github.io/luxon/

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O0Ma2XuyTbwi2HLyfZ3d62LQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。
领券