【n8n教程】:掌握n8n数据处理 - 从基础到实战

在使用n8n进行工作流自动化时,数据处理是核心技能。无论是从API获取数据、转换格式、还是在不同节点之间映射数据,理解n8n的数据结构都是必不可少的。本教程将带你从零开始理解n8n的数据流、数据映射和数据转换,并通过实际案例帮助你快速掌握这一关键能力。


第一部分:理解n8n的数据结构

什么是n8n中的数据?

n8n中的数据是指节点接收和处理的信息。在底层,所有在节点之间传递的数据都遵循一个统一的结构。

核心数据结构

n8n中所有数据都以JSON对象数组的形式传递。每个数据项都有这样的结构:


    
    
    
  [
  {

    "json"
: {
      "字段名"
: "值",
      "另一个字段"
: "另一个值"
    }

  }
,
  {

    "json"
: {
      "字段名"
: "值2",
      "另一个字段"
: "另一个值2"
    }

  }

]

关键概念:

概念说明示例
Item(项目)数据的单个单元一条用户记录、一个订单
json 键包含实际数据的对象{ "name": "John", "age": 30 }
数组多个item组成的集合[item1, item2, item3]

简单示例

假设你从HTTP请求节点获取了一个用户列表,数据可能是这样的:


    
    
    
  [
  {

    "json"
: {
      "id"
: 1,
      "name"
: "李四",
      "email"
: "lisi@example.com",
      "status"
: "active"
    }

  }
,
  {

    "json"
: {
      "id"
: 2,
      "name"
: "王五",
      "email"
: "wangwu@example.com",
      "status"
: "inactive"
    }

  }

]

这个数组包含了2个item,每个item代表一个用户。


第二部分:数据在节点中的流动

节点如何处理多个数据项

n8n中的每个节点都可以逐个处理多个数据项。这是n8n设计的核心特性。

例子:创建Trello卡片

如果你配置一个Trello节点来"创建卡片",并使用表达式 {{ $json.name }} 来设置卡片名称,当输入包含3个item时:

输入数据操作输出
item1: name = "任务1"创建卡片创建了名为"任务1"的卡片
item2: name = "任务2"创建卡片创建了名为"任务2"的卡片
item3: name = "任务3"创建卡片创建了名为"任务3"的卡片

最后,Trello中会有3张新卡片

理解这意味着什么

这种设计让你可以:


第三部分:数据映射 - 在节点间传递数据

什么是数据映射?

数据映射是指从前一个节点的输出中引用数据,并将其传递给下一个节点的过程。它不涉及数据转换,只是引用。

方法1:拖拽式映射(最直观)

这是初学者最推荐的方法:

步骤:

  1. 1. 运行你的工作流以加载数据
  2. 2. 打开需要映射数据的节点
  3. 3. 在INPUT面板中找到你要使用的数据
  4. 4. 点击并按住要映射的字段
  5. 5. 拖拽到你要使用的参数字段中
  6. 6. n8n会自动生成表达式

例子:

假设你的HTTP Request节点返回了这样的数据:


    
    
    
  {
  "json"
: {
    "customer_name"
: "张三",
    "customer_email"
: "zhangsan@example.com",
    "order_total"
: 299.99
  }

}

现在你要在Gmail节点中使用 customer_name。只需在INPUT面板中拖拽 customer_name 字段到Gmail的"收件人名称"参数,n8n会自动生成表达式:


    
    
    
  {{ $json.customer_name }}

方法2:表达式编辑器(更灵活)

对于更复杂的需求,你可以直接在表达式编辑器中编写:


    
    
    
  // 访问顶级字段
{{ $json.fieldName }}

// 访问嵌套字段
{{ $json.user.profile.email }}

// 访问数组元素
{{ $json.items[0].name }}

// 使用默认值
{{ $json.optionalField || 'default value' }}

实际示例:


    
    
    
  // 组合多个字段
{{ $json.first_name }} {{ $json.last_name }}

// 结果:张三 李四

// 简单计算
{{ $json.price * $json.quantity }}

// 条件赋值
{{ $json.status === 'premium' ? $json.price * 0.9 : $json.price }}

理解嵌套数据映射

如果你的数据结构是这样的:


    
    
    
  {
  "json"
: {
    "user"
: {
      "profile"
: {
        "name"
: "李四",
        "email"
: "lisi@example.com"
      }

    }
,
    "order"
: {
      "id"
: 12345,
      "items"
: ["商品1", "商品2"]
    }

  }

}

你可以这样访问:

需要的数据表达式结果
用户名{{ $json.user.profile.name }}李四
邮箱{{ $json.user.profile.email }}lisi@example.com[1]
订单ID{{ $json.order.id }}12345
第一个商品{{ $json.order.items[0] }}商品1

第四部分:数据转换

为什么需要数据转换?

从外部系统获取的数据格式可能与n8n的标准数据结构不兼容。你需要将其转换为n8n可以处理的格式。

常用的数据转换节点

节点功能使用场景
Split Out将单个包含列表的item分成多个itemAPI返回了嵌套数组,需要逐个处理
Aggregate将多个item组合成单个item或分组需要汇总或合并数据
Remove Duplicates删除重复的item清理重复数据
Sort排序item按字段排序数据
Limit限制item数量只保留前N条记录
Summarize类似Excel数据透视表的聚合生成统计数据

实际示例:Split Out节点

场景: 你的API返回了这样的数据:


    
    
    
  {
  "json"
: {
    "products"
: [
      {
 "id": 1, "name": "手机", "price": 3999 },
      {
 "id": 2, "name": "电脑", "price": 6999 },
      {
 "id": 3, "name": "平板", "price": 2999 }
    ]

  }

}

问题: 这是1个item,但你需要为每个产品创建一条记录。

解决方案: 使用Split Out节点,选择要分割的字段为 products

输出: 3个item,每个代表一个产品


    
    
    
  // Item 1
{
 "json": { "id": 1, "name": "手机", "price": 3999 } }

// Item 2

{
 "json": { "id": 2, "name": "电脑", "price": 6999 } }

// Item 3

{
 "json": { "id": 3, "name": "平板", "price": 2999 } }

第五部分:使用代码处理数据

Function节点 vs Code节点

特性Function节点Code节点
语言JavaScriptJavaScript / Python
复杂度简单单行代码更复杂的逻辑
自动处理自动添加json键和数组从0.166.0版本后也自动处理
文件大小不可处理可处理

Function节点示例

场景: 你需要为每个用户生成一个欢迎邮件,并创建一个新字段 greeting


    
    
    
  // 输入:{ "json": { "name": "李四" } }

return
 {
  json
: {
    ...($json), // 保留原有字段
    greeting
: `尊敬的 ${$json.name},欢迎使用我们的服务!`,
    processed_at
: new Date().toISOString()
  }
};

// 输出:

// {

//   "json": {

//     "name": "李四",

//     "greeting": "尊敬的 李四,欢迎使用我们的服务!",

//     "processed_at": "2025-12-04T14:02:00Z"

//   }

// }

Code节点示例 - 处理多个item


    
    
    
  // 处理所有输入item
const
 items = $input.all();

const
 result = items
  .filter(item => item.json.age >= 18) // 筛选成年人
  .map(item => ({
    json
: {
      ...item.json,
      category
: item.json.age < 30 ? '青年' : '中年',
      verified
: true
    }
  }));

return
 result;

重要提示: 从n8n 0.166.0版本开始,Function和Code节点会自动处理json键和数组包装,让代码编写更简洁。


第六部分:数据固定与编辑 - 开发时的利器

什么是数据固定(Data Pinning)?

数据固定是指保存节点的输出数据,并在后续测试中使用这个保存的数据,而不是每次都重新获取。

好处:

如何固定数据

  1. 1. 运行节点以加载数据
  2. 2. 在OUTPUT面板中找到Pin data按钮
  3. 3. 点击Pin data
  4. 4. 一个横幅会显示"This data is pinned"

现在,即使外部系统数据改变,下次运行时也会使用固定的数据。

如何编辑固定数据

有时你想测试不同的场景。你可以编辑固定的数据:

  1. 1. 在OUTPUT面板中选择JSON标签
  2. 2. 点击Edit按钮
  3. 3. 修改JSON数据
  4. 4. 点击Save保存

这对于测试边界情况非常有用:


第七部分:项目链接 - 高级概念

什么是项目链接(Item Linking)?

当节点处理多个item时,n8n会自动跟踪每个输出item与哪个输入item相关。这就是项目链接

自动项目链接规则

n8n会自动尝试链接item:

输入输出链接方式
1个1个输出链接到输入
1个多个所有输出都链接到这个输入
多个多个(数量相等)按顺序一一对应

在表达式中访问链接的item

在表达式编辑器中,你可以访问之前节点中的item:


    
    
    
  // 访问前一个节点中的链接item
{{ $item(0).$json.original_field }}

// 在多步工作流中回溯
{{ $item("NodeName").$json.fieldName }}

例子:

假设你有一个工作流:

  1. 1. HTTP Request 获取用户
  2. 2. Code节点 - 处理用户数据
  3. 3. Google Sheets - 将数据写入

在Google Sheets节点中,如果你想引用HTTP Request节点中的原始用户名:


    
    
    
  {{ $item("HTTP Request").$json.username }}

第八部分:数据表 - 在工作流中存储数据

什么是数据表?

数据表是n8n内置的轻量级数据存储,无需外部数据库就可以在工作流中存储和管理数据。

使用场景

快速使用步骤

第一步:创建数据表

  1. 1. 进入n8n项目
  2. 2. 点击Data tables标签
  3. 3. 点击Create Data table
  4. 4. 输入表名并添加列

第二步:在工作流中使用

使用Data table节点来:

例子:防止重复运行


    
    
    
  // 在Data table中存储已处理的订单ID
// 每次运行时查询这个表,检查订单是否已处理

第九部分:实战案例 - 完整可执行工作流

场景介绍

你需要创建一个工作流,用来:

  1. 1. 从模拟API获取产品列表
  2. 2. 对产品进行转换和过滤
  3. 3. 将数据分解为单个item
  4. 4. 添加计算字段
  5. 5. 输出最终结果

工作流代码

以下是一个完整的可导入工作流JSON:


    
    
    
  {
  "name"
: "Product Data Processing Workflow",
  "nodes"
: [
    {

      "parameters"
: {},
      "name"
: "Manual Trigger",
      "type"
: "n8n-nodes-base.manualTrigger",
      "typeVersion"
: 1,
      "position"
: [250, 300]
    }
,
    {

      "parameters"
: {
        "jsCode"
: "return [\n  {\n    json: {\n      products: [\n        { id: 1, name: '手机', price: 3999, stock: 50, category: 'electronics' },\n        { id: 2, name: '平板', price: 2999, stock: 30, category: 'electronics' },\n        { id: 3, name: '充电器', price: 99, stock: 200, category: 'accessories' },\n        { id: 4, name: '手机壳', price: 49, stock: 500, category: 'accessories' }\n      ]\n    }\n  }\n];"
      }
,
      "name"
: "Simulate API Response",
      "type"
: "n8n-nodes-base.code",
      "typeVersion"
: 2,
      "position"
: [450, 300]
    }
,
    {

      "parameters"
: {
        "fieldToSplitOut"
: "products"
      }
,
      "name"
: "Split Products",
      "type"
: "n8n-nodes-base.splitOut",
      "typeVersion"
: 1,
      "position"
: [650, 300]
    }
,
    {

      "parameters"
: {
        "fields"
: {
          "values"
: [
            {

              "name"
: "id",
              "type"
: "nb:number",
              "extractValue"
: "={{ $json.id }}"
            }
,
            {

              "name"
: "name",
              "type"
: "nb:string",
              "extractValue"
: "={{ $json.name }}"
            }
,
            {

              "name"
: "price",
              "type"
: "nb:number",
              "extractValue"
: "={{ $json.price }}"
            }
,
            {

              "name"
: "stock",
              "type"
: "nb:number",
              "extractValue"
: "={{ $json.stock }}"
            }
,
            {

              "name"
: "category",
              "type"
: "nb:string",
              "extractValue"
: "={{ $json.category }}"
            }
,
            {

              "name"
: "in_stock",
              "type"
: "nb:boolean",
              "extractValue"
: "={{ $json.stock > 0 }}"
            }
,
            {

              "name"
: "tax",
              "type"
: "nb:number",
              "extractValue"
: "={{ ($json.price * 0.13).toFixed(2) }}"
            }
,
            {

              "name"
: "final_price",
              "type"
: "nb:number",
              "extractValue"
: "={{ ($json.price + ($json.price * 0.13)).toFixed(2) }}"
            }

          ]

        }

      }
,
      "name"
: "Add Calculated Fields",
      "type"
: "n8n-nodes-base.set",
      "typeVersion"
: 3,
      "position"
: [850, 300]
    }
,
    {

      "parameters"
: {
        "jsCode"
: "// 只返回库存不足的产品\nif ($json.stock < 100) {\n  return { json: $json };\n}"
      }
,
      "name"
: "Filter Low Stock",
      "type"
: "n8n-nodes-base.code",
      "typeVersion"
: 2,
      "position"
: [1050, 300]
    }

  ]
,
  "connections"
: {
    "Manual Trigger"
: {
      "main"
: [
        [

          {

            "node"
: "Simulate API Response",
            "type"
: "main",
            "index"
: 0
          }

        ]

      ]

    }
,
    "Simulate API Response"
: {
      "main"
: [
        [

          {

            "node"
: "Split Products",
            "type"
: "main",
            "index"
: 0
          }

        ]

      ]

    }
,
    "Split Products"
: {
      "main"
: [
        [

          {

            "node"
: "Add Calculated Fields",
            "type"
: "main",
            "index"
: 0
          }

        ]

      ]

    }
,
    "Add Calculated Fields"
: {
      "main"
: [
        [

          {

            "node"
: "Filter Low Stock",
            "type"
: "main",
            "index"
: 0
          }

        ]

      ]

    }

  }

}

工作流说明

节点功能详解:

  1. 1. Manual Trigger - 手动触发工作流
  2. 2. Simulate API Response - 模拟从API获取的产品列表
    • • 返回包含products数组的JSON
  3. 3. Split Products - 拆分数据
    • • 输入:1个包含4个产品的item
    • • 输出:4个独立的item,每个代表一个产品
  4. 4. Add Calculated Fields - 使用Set节点添加新字段
    • in_stock: 是否有库存(布尔值)
    • tax: 税金计算(价格×13%)
    • final_price: 最终价格(含税)
  5. 5. Filter Low Stock - 过滤操作
    • • 只保留库存<100的产品

如何使用这个工作流

步骤1:导入工作流

步骤2:运行工作流

步骤3:理解数据转换过程

步骤4:修改和扩展

预期输出示例

执行完整工作流后,最后的Filter Low Stock节点会输出:


    
    
    
  [
  {

    "json"
: {
      "id"
: 1,
      "name"
: "手机",
      "price"
: 3999,
      "stock"
: 50,
      "category"
: "electronics",
      "in_stock"
: true,
      "tax"
: "519.87",
      "final_price"
: "4518.87"
    }

  }
,
  {

    "json"
: {
      "id"
: 3,
      "name"
: "充电器",
      "price"
: 99,
      "stock"
: 200,
      "category"
: "accessories",
      "in_stock"
: true,
      "tax"
: "12.87",
      "final_price"
: "111.87"
    }

  }
,
  {

    "json"
: {
      "id"
: 4,
      "name"
: "手机壳",
      "price"
: 49,
      "stock"
: 500,
      "category"
: "accessories",
      "in_stock"
: true,
      "tax"
: "6.37",
      "final_price"
: "55.37"
    }

  }

]

注意: 平板(id: 2)被过滤掉了,因为其库存(30)小于100。


关键要点总结

n8n所有数据都是JSON对象数组 - 每个item都包含一个json键

节点逐个处理item - 一个表达式应用于每个item

数据映射是数据流的基础 - 拖拽或表达式都可以实现

数据转换处理不兼容的格式 - Split Out、Aggregate等节点是你的工具

代码节点提供强大的灵活性 - Function和Code节点用于复杂操作

数据固定加速开发 - 避免重复API调用

项目链接追踪数据来源 - 高级工作流必须理解

在小规模数据存储使用数据表 - 无需外部数据库


常见问题解答

Q:为什么我的表达式 $json.fieldName 返回undefined?

A:可能是因为:

  1. 1. 字段名拼写错误(JSON大小写敏感)
  2. 2. 字段在嵌套对象中 - 使用 $json.parent.child
  3. 3. 该字段不存在 - 检查前一个节点的OUTPUT

Q:如何同时处理多个来源的数据?

A:使用Merge节点来组合多个节点的输出,然后使用表达式访问每个源的数据。

Q:Split Out和Aggregate有什么区别?

A:Split Out将1个包含列表的item分成多个item;Aggregate将多个item组合成1个。它们是相反的操作。

Q:我能在工作流中存储10GB的数据吗?

A:不能。数据表的默认限制是50MB。使用真实数据库(MySQL、PostgreSQL)来存储大规模数据。


官方文档[2]
n8n系列教程[3]

引用链接

[1] lisi@example.com: mailto:lisi@example.com
[2] 官方文档: https://docs.n8n.io/data/
[3] n8n系列教程: https://www.undsky.com/blog/?category=n8n%E6%95%99%E7%A8%8B#