n8n入门教程系列目录
【n8n入门教程01】n8n工作流自动化平台架构解析与核心概念详解
【n8n入门教程02】macOS安装n8n保姆级教程-Homebrew与npm两种方式详解
【n8n入门教程03】n8n变量配置与多输入数据合并完整指南
【n8n入门教程04】n8n权限与路径管理全指南:避免常见错误,保障数据安全
【n8n入门教程05】n8n Workflow编辑器完全指南:从入门到精通
【n8n入门教程06】n8n常用节点完全指南:从文件操作到代码执行
【n8n入门教程08】n8n触发节点完全指南:定时器、Webhook和手动触发
【n8n入门教程09】n8n Code与Execute Command节点深度对比与最佳实践
【n8n入门教程10】n8n本地程序集成完全指南:使用Execute Command节点
【n8n入门教程11】n8n大模型集成完全指南:调用OpenAI和Gemini API
【n8n入门教程12】n8n PDF翻译自动化实战:从英文PDF到中文PDF
在自动化系统中,灵活的配置能力是高效运维和安全保障的基础。本文将系统介绍n8n的环境变量、内置变量与表达式,并重点说明当一个节点有多个输入时如何正确获取与合并数据的几种方法,包括官方推荐用法与Code节点示例。
环境变量配置(自托管部署)
n8n的大部分服务端行为都可以通过环境变量进行配置,这让系统具有了很强的灵活性和可定制性。下面是一些最常用的环境变量及其作用:
| 变量 | 作用 | 常见取值/示例 |
|---|---|---|
| N8N_DEFAULT_BINARY_DATA_MODE | 二进制数据存储模式 | default(内存+临时文件,默认)、filesystem |
| EXECUTIONS_DATA_PRUNE | 是否滚动清理历史执行数据 | true/false |
| EXECUTIONS_DATA_MAX_AGE | 执行数据最大保留时长(小时) | 例如336(两周) |
| EXECUTIONS_DATA_PRUNE_MAX_COUNT | 最多保留执行条数(0表示不限制) | 如10000 |
| N8N_DEFAULT_LOCALE | UI默认语言(回退为en) | 如en、de;不支持区域化标识如de-AT |
| GENERIC_TIMEZONE | 实例时区(影响定时等) | 如Asia/Shanghai |
| N8N_BLOCK_ENV_ACCESS_IN_NODE | 是否禁止在表达式/Code中访问$env | true/false。设为true会禁用$env |
重要提示
从n8n 1.0版本开始,已经移除了面向UI的Basic Auth/JWT登录,改为用户管理/SSO等方式。如果你之前使用N8N_BASIC_AUTH_*来保护编辑器登录,这是旧设定,现在已经不适用了。请改用用户管理/SSO。
设置环境变量后需要重启n8n才能生效。
内置变量与表达式速查
n8n在表达式与Code节点中提供了一组强大的内置变量和方法,熟练掌握这些工具可以大大提高工作效率。
当前节点输入(最常用)
$json:等同于$input.item.json(在”逐条运行”模式下可用)$input.item/$input.all()/$input.first()/$input.last()/$input.params
这些API在表达式和Code节点中都可用(Python用_input/_json同名变体)。
时间相关
$now、$today:Luxon DateTime对象,便于格式化和运算
其他节点输出(跨节点取数)
$('<节点名>').all()/.first()/.last()/.params.itemMatching(i):在Code节点里,用来”顺着item链接”找到与当前第i个输入对应的上游item
这些方法在表达式和Code中都可用,对item链接的支持更加一致。
环境变量
$env.MY_ENV(若未被N8N_BLOCK_ENV_ACCESS_IN_NODE禁用)
多输入节点:如何同时获取并合并数据?
这是n8n开发中最容易踩坑的地方,需要特别注意。
核心事实(避免踩坑)
事实一:当一个节点有多个输入时
n8n通常会为每个输入分别执行一次(或按item链接执行)。在这种情况下:
$json和$input.*只代表”本次执行对应的那个输入”- 表达式里没有
$input(1)这种函数;$input是对象,不是函数。把$input当函数调用会得到错误:$input is not a function
正确的用法是$input.all()、$input.first()等。
事实二:想要在同一次执行中同时拿到多个上游的结果
有两种官方认可的方式:
- 方案A:先用Merge节点把两路数据合成一路
- 方案B:在表达式/Code中直接用
$('<节点名>')按名称取上游节点输出,必要时配合.itemMatching(i)精准配对
方案A:用Merge节点统一输入(推荐)
当你希望下游节点只处理一条合并后的item或者成对合并两路列表时,使用Merge节点是最省心的选择。
Merge支持多种模式:
- Append:追加模式
- Combine:按字段合并
- Merge by Position:按位置一一合并
- Full Combination:全组合
- Choose Branch:选择分支
常见的”按位置一一合并”在新版UI中归入Combine → Merge by Position。
方案B:在表达式/Code中按节点名取数据
无需额外Merge,你可以在任意节点的表达式或Code节点中直接取上游任意节点的输出。
表达式示例
{{$("HTTP Request").first().json.result}}{{$("DB Query").last().json.rows}}注意:$node["节点名"].json仍然可用,但$()系列在1.x版本中对item链接的支持更加一致。
Code(JS)示例
const http = $('HTTP Request').first().json;const db = $('DB Query').first().json;return [{ json: { ...http, ...db } }];$('…')系列在表达式与Code节点中均可用。
Code节点:两个JSON同时合并的正确示例
在Code节点的Mode里通常选择Run Once(一次运行输出一个结果)或Run Once for Each Item(逐条处理)。下面给出几种常见场景的具体实现。
场景1:两路各出一条,合并成一条(Run Once for All Item)
这段代码用于在n8n的JavaScript Code节点中,处理”Run Once for All Item”模式下的多路输入配对合并。
// Code 节点(JavaScript),Mode: Run Once for All Item
const a = $('输入 A').first().json; // 读取名为"输入 A"的上游节点第一条const b = $('输入 B').first().json; // 读取名为"输入 B"的上游节点第一条
return [{ json: { ...a, ...b } }];说明:该写法不依赖当前节点的多输入执行顺序,直接按名字取上游。
场景2:两路各出多条,按位置一一配对合并(Run Once for Each Item)
这段代码演示了在JavaScript的Code节点中,如何在”Run Once for Each Item”模式下,针对多路输入的每一条数据进行精准配对合并。
通过itemMatching(i)方法,可以确保每个输出item都是由”输入A”和”输入B”中第i条数据一一对应合并而成。这种写法非常适用于需要保持输入数据顺序一致、逐条处理的场景,避免了因多分支或数据乱序导致的配对错误。
// Code 节点(JavaScript),Mode: Run Once for Each Item// 依赖 item 链接,使用 itemMatching(i) 精准找回与第 i 个输入配对的上游 item
const inputItems = $input.all(); // 当前输入的全部 itemsconst out = [];
for (let i = 0; i < inputItems.length; i++) { const a = $('输入 A').itemMatching(i).json; // 与当前第 i 条对应的"输入 A"上游 item const b = $('输入 B').itemMatching(i).json; // 与当前第 i 条对应的"输入 B"上游 item out.push({ json: { ...a, ...b } });}
return out;说明:.itemMatching(i)是Code节点专用的”沿item链接回溯”的方法,它能在多分支/合并之后,依然找回与当前第i条相匹配的上游item。官方cookbook示例也使用这种写法。
场景3:如果你明确希望”先合后用”
在Code前放一个Merge(Combine → Merge by Position/Fields),把两路合成一条/一组,再在Code里直接用$json即可:
// Merge → Code,Code 逐条模式const a = $json.a; // Merge 后统一结构中的 aconst b = $json.b; // Merge 后统一结构中的 breturn [{ json: { ...a, ...b } }];提示:当合并策略、冲突字段优先级或去重策略比较复杂时,Merge节点更直观可靠。
常见表达式与函数
在实际开发中,这些表达式和函数会经常用到:
- 读取字段:
{{$json.id}}/{{$("Set").item.json.value}} - 三元判断:
{{$json.name ? $json.name : "unknown"}} - 默认值:
{{$json.x ?? "default"}} - 时间处理:
{{$now.toISO()}}、{{$today.toISODate()}}
注意:数据转换函数(如toDateTime()、parseJson()等)是表达式编辑器提供的”Data transformation functions”,不在Code节点内置。
常见错误与排查
错误1:TypeError: $input is not a function
原因:把$input当函数调用(如$input(1))。
解决:$input是对象,用$input.all()、$input.first()、$input.item;多上游请用$("<节点>").…或先Merge。
错误2:拿不到另一条输入的数据
说明:当前这次执行只关联其中一路输入。
解决:用Merge整合,或在表达式/Code通过节点名取数,并在Code中配合.itemMatching(i)。
错误3:访问$env为空
检查:是否设置了N8N_BLOCK_ENV_ACCESS_IN_NODE=true。
两种方案对比
下图直观展示了两种处理多输入的方式:
说明:
- 方案A(Merge):Merge → 下游直接用json字段,简单直观
- 方案B(直接取数):在表达式/Code里按节点名读取,更灵活但需要理解item链接机制
- 表达式里:
$("HTTP Request").first().json - Code里多条配对:用
itemMatching进行位置对应
- 表达式里:
总结
下面总结了多输入节点数据获取与合并的常用方法和注意事项:
单输入场景
直接用$json / $input.*即可。
多输入场景
- 想要一次性看到两路数据 → 先Merge
- 不想Merge或需精准配对 → 在表达式/Code中用
$('<节点>'),并在Code中用.itemMatching(i)
重要提醒
- 不要写
$input(1),$input不是函数 - 理解item链接机制对于复杂工作流至关重要
- Merge节点虽然增加了工作流复杂度,但在很多情况下是最可靠的解决方案
掌握这些变量配置和数据合并技巧,你就能更加灵活地构建复杂的自动化工作流,充分发挥n8n的强大功能。