变量与配置
在自动化系统中,灵活的配置能力是高效运维和安全保障的基础。本文系统介绍 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
:LuxonDateTime
对象,便于格式化/运算。
- 其他节点输出(跨节点取数,支持表达式与 Code)
$('<节点名>').all()
/.first()
/.last()
/.params
。.itemMatching(i)
:在 Code 节点里,用来“顺着 item 链接(item linking)”找到与当前第i
个输入对应的上游 item。
- 环境变量:
$env.MY_ENV
(若未被N8N_BLOCK_ENV_ACCESS_IN_NODE
禁用)。
多输入节点:如何同时获取并合并数据?
核心事实(避免踩坑):
- 一个节点有多个输入时,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/按字段、按位置、全组合、Choose Branch 等),常见的“按位置一一合并”在新版 UI 归入 Combine → Merge by Position。
Merge 的行为与 item 链接关系密切。合并后如何保持/恢复链接,详见“Item linking”文档与示例。
方案 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(); // 当前输入的全部 items
const 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 后统一结构中的 a
const b = $json.b; // Merge 后统一结构中的 b
return [{ 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 节点内置。
常见错误与排查
TypeError: $input is not a function
原因:把$input
当函数调用(如$input(1)
)。 解决:$input
是对象,用$input.all()
、$input.first()
、$input.item
;多上游请用$("<节点>").…
或先 Merge。- 拿不到另一条输入的数据
说明:当前这次执行只关联其中一路输入。用 Merge 整合,或在表达式/Code 通过 节点名取数,并在 Code 中配合
.itemMatching(i)
。 - 访问
$env
为空 检查是否设置了N8N_BLOCK_ENV_ACCESS_IN_NODE=true
。
一图看懂
两条路径对比如下图所示:
说明:
- 方案 A(Merge):Merge → 下游直接用
json
字段。 - 方案 B(直接取数):在表达式/Code里按节点名读取:
- 表达式里:示意
$("HTTP Request").first().json
(不要把这串放进图里)。 - Code 里多条配对:用
itemMatching
进行位置对应。
- 表达式里:示意
结论
下面总结了多输入节点数据获取与合并的常用方法和注意事项:
- 单输入:直接用
$json
/$input.*
。 - 多输入:
- 想要一次性看到两路数据 → 先 Merge。
- 不想 Merge 或需精准配对 → 在 表达式/Code 中用
$('<节点>')
,并在 Code 中用.itemMatching(i)
。
- 不要写
$input(1)
,$input
不是函数。