Skip to content

n8n 变量与表达式系统 - 动态工作流的核心

n8n 的表达式系统是其最强大的功能之一,它让工作流能够动态地处理数据、做出决策和适应不同的场景。今天我们来深入学习这个系统的各个方面。

表达式基础语法

基本格式

n8n 表达式使用双花括号包围:

javascript
{{ expression }}

数据引用

当前节点数据

javascript
{{ $json.fieldName }}          // 引用当前数据的字段
{{ $json["field name"] }}      // 字段名包含空格或特殊字符
{{ $json.user.name }}          // 嵌套对象
{{ $json.items[0] }}           // 数组元素
{{ $json.items.length }}       // 数组长度

其他节点数据

javascript
{{ $node["Node Name"].json }}           // 引用指定节点的数据
{{ $node["HTTP Request"].json.result }} // 引用节点的特定字段
{{ $('Node Name').item.json }}          // 另一种引用方式

全局变量

javascript
{{ $now }}                     // 当前时间
{{ $today }}                   // 今天日期
{{ $workflow.id }}             // 工作流 ID
{{ $workflow.name }}           // 工作流名称
{{ $execution.id }}            // 执行 ID
{{ $execution.mode }}          // 执行模式

数据类型操作

字符串操作

javascript
// 基本字符串操作
{{ $json.name.toLowerCase() }}         // 转小写
{{ $json.name.toUpperCase() }}         // 转大写
{{ $json.name.trim() }}                // 去除首尾空格
{{ $json.name.length }}                // 字符串长度

// 字符串拼接
{{ $json.firstName + ' ' + $json.lastName }}
{{ `Hello, ${$json.name}!` }}          // 模板字符串

// 字符串查找和替换
{{ $json.text.includes('keyword') }}   // 是否包含
{{ $json.text.indexOf('keyword') }}    // 查找位置
{{ $json.text.replace('old', 'new') }} // 替换
{{ $json.text.split(',') }}            // 分割字符串

// 字符串截取
{{ $json.text.substring(0, 10) }}      // 截取前10个字符
{{ $json.text.slice(-5) }}             // 截取后5个字符

数字操作

javascript
// 数学运算
{{ $json.price * 1.1 }}               // 乘法
{{ $json.total / $json.count }}       // 除法
{{ $json.amount + $json.tax }}        // 加法
{{ $json.budget - $json.spent }}      // 减法
{{ $json.value % 10 }}                // 取余

// 数学函数
{{ Math.round($json.value) }}         // 四舍五入
{{ Math.floor($json.value) }}         // 向下取整
{{ Math.ceil($json.value) }}          // 向上取整
{{ Math.abs($json.value) }}           // 绝对值
{{ Math.max($json.a, $json.b) }}      // 最大值
{{ Math.min($json.a, $json.b) }}      // 最小值

// 数字格式化
{{ $json.price.toFixed(2) }}          // 保留2位小数
{{ $json.value.toLocaleString() }}    // 本地化格式

数组操作

javascript
// 数组基本操作
{{ $json.items.length }}              // 数组长度
{{ $json.items[0] }}                  // 第一个元素
{{ $json.items.slice(-1)[0] }}        // 最后一个元素

// 数组方法
{{ $json.tags.join(', ') }}           // 连接数组元素
{{ $json.numbers.sort() }}            // 排序
{{ $json.items.reverse() }}           // 反转

// 数组过滤和映射
{{ $json.items.filter(item => item.active) }}
{{ $json.numbers.map(n => n * 2) }}
{{ $json.items.find(item => item.id === 123) }}

// 数组聚合
{{ $json.numbers.reduce((sum, n) => sum + n, 0) }}
{{ $json.items.some(item => item.urgent) }}
{{ $json.items.every(item => item.valid) }}

对象操作

javascript
// 对象属性
{{ Object.keys($json.user) }}         // 获取所有键
{{ Object.values($json.user) }}       // 获取所有值
{{ Object.entries($json.user) }}      // 获取键值对数组

// 对象合并
{{ Object.assign({}, $json.user, $json.profile) }}
{{ {...$json.user, ...$json.profile} }}

// 属性检查
{{ $json.user.hasOwnProperty('email') }}
{{ 'email' in $json.user }}

日期时间处理

基本日期操作

javascript
// 当前时间
{{ $now }}                            // 当前时间戳
{{ $today }}                          // 今天日期
{{ new Date() }}                      // 当前日期对象

// 日期创建
{{ new Date($json.dateString) }}      // 从字符串创建
{{ new Date($json.timestamp) }}       // 从时间戳创建

// 日期格式化
{{ $now.toISOString() }}              // ISO 格式
{{ $now.toDateString() }}             // 日期字符串
{{ $now.toTimeString() }}             // 时间字符串
{{ $now.toLocaleDateString('zh-CN') }} // 本地化日期

日期计算

javascript
// 日期加减
{{ $now.plus({days: 7}) }}            // 7天后
{{ $now.minus({hours: 2}) }}          // 2小时前
{{ $now.plus({months: 1, days: 15}) }} // 1个月15天后

// 日期比较
{{ $json.startDate < $json.endDate }} // 日期比较
{{ $now.diff($json.createdAt, 'days') }} // 天数差
{{ $now.diff($json.createdAt, 'hours') }} // 小时差

// 日期格式化
{{ $now.format('YYYY-MM-DD') }}       // 自定义格式
{{ $now.format('YYYY-MM-DD HH:mm:ss') }}
{{ $now.format('dddd, MMMM Do YYYY') }}

时区处理

javascript
// 时区转换
{{ $now.tz('Asia/Shanghai') }}        // 转换到指定时区
{{ $now.utc() }}                      // 转换到 UTC
{{ $now.local() }}                    // 转换到本地时区

// 时区信息
{{ $now.tz('Asia/Shanghai').format('Z') }} // 时区偏移
{{ $now.tz('Asia/Shanghai').zoneName() }}  // 时区名称

条件表达式

三元运算符

javascript
// 基本三元运算
{{ $json.age >= 18 ? 'adult' : 'minor' }}
{{ $json.score > 60 ? 'pass' : 'fail' }}

// 嵌套三元运算
{{ $json.score >= 90 ? 'A' : $json.score >= 80 ? 'B' : $json.score >= 70 ? 'C' : 'D' }}

// 空值处理
{{ $json.name || 'Unknown' }}         // 空值默认值
{{ $json.email ?? 'no-email@example.com' }} // null/undefined 默认值

复杂条件

javascript
// 逻辑运算
{{ $json.age >= 18 && $json.hasLicense }}
{{ $json.type === 'premium' || $json.type === 'vip' }}
{{ !$json.isDeleted }}

// 范围检查
{{ $json.score >= 60 && $json.score <= 100 }}
{{ ['active', 'pending'].includes($json.status) }}

// 正则表达式
{{ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test($json.email) }}
{{ $json.phone.match(/^\d{11}$/) }}

高级表达式技巧

函数定义和调用

javascript
// 定义辅助函数
{{ 
  (() => {
    const formatCurrency = (amount) => {
      return new Intl.NumberFormat('zh-CN', {
        style: 'currency',
        currency: 'CNY'
      }).format(amount);
    };
    
    return formatCurrency($json.price);
  })()
}}

// 复杂数据处理
{{
  (() => {
    const data = $json.items;
    const grouped = data.reduce((acc, item) => {
      const category = item.category || 'other';
      if (!acc[category]) acc[category] = [];
      acc[category].push(item);
      return acc;
    }, {});
    
    return Object.keys(grouped).map(category => ({
      category,
      items: grouped[category],
      count: grouped[category].length,
      total: grouped[category].reduce((sum, item) => sum + item.value, 0)
    }));
  })()
}}

错误处理

javascript
// 安全的属性访问
{{ $json.user?.profile?.name || 'Unknown' }}
{{ $json.items?.[0]?.title || 'No title' }}

// Try-catch 表达式
{{
  (() => {
    try {
      return JSON.parse($json.jsonString);
    } catch (error) {
      return { error: 'Invalid JSON', original: $json.jsonString };
    }
  })()
}}

// 数据验证
{{
  (() => {
    const email = $json.email;
    if (!email) return { valid: false, error: 'Email is required' };
    
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
      return { valid: false, error: 'Invalid email format' };
    }
    
    return { valid: true, email: email.toLowerCase() };
  })()
}}

环境变量和配置

环境变量访问

javascript
// 访问环境变量
{{ $env.API_KEY }}                    // 环境变量
{{ $env.DATABASE_URL }}               // 数据库连接
{{ $env.NODE_ENV || 'development' }}  // 带默认值

// 配置管理
{{
  (() => {
    const config = {
      development: {
        apiUrl: 'http://localhost:3000',
        debug: true
      },
      production: {
        apiUrl: 'https://api.example.com',
        debug: false
      }
    };
    
    const env = $env.NODE_ENV || 'development';
    return config[env];
  })()
}}

动态配置

javascript
// 基于时间的配置
{{
  (() => {
    const hour = new Date().getHours();
    
    if (hour >= 9 && hour <= 17) {
      return {
        priority: 'high',
        timeout: 5000,
        retries: 3
      };
    } else {
      return {
        priority: 'low',
        timeout: 10000,
        retries: 1
      };
    }
  })()
}}

// 基于数据的配置
{{
  (() => {
    const userType = $json.userType;
    const configs = {
      premium: { limit: 1000, features: ['advanced', 'priority'] },
      standard: { limit: 100, features: ['basic'] },
      trial: { limit: 10, features: ['basic'] }
    };
    
    return configs[userType] || configs.trial;
  })()
}}

性能优化

表达式缓存

javascript
// 缓存复杂计算结果
{{
  (() => {
    const cacheKey = `calc_${$json.id}`;
    
    if ($workflow.context[cacheKey]) {
      return $workflow.context[cacheKey];
    }
    
    // 复杂计算
    const result = expensiveCalculation($json.data);
    
    // 缓存结果
    $workflow.context[cacheKey] = result;
    
    return result;
  })()
}}

避免重复计算

javascript
// 将计算结果存储在变量中
{{
  (() => {
    const user = $json.user;
    const now = new Date();
    const age = Math.floor((now - new Date(user.birthDate)) / (365.25 * 24 * 60 * 60 * 1000));
    
    return {
      ...user,
      age,
      isAdult: age >= 18,
      category: age >= 65 ? 'senior' : age >= 18 ? 'adult' : 'minor'
    };
  })()
}}

调试表达式

调试技巧

javascript
// 添加调试信息
{{
  (() => {
    const debug = {
      input: $json,
      timestamp: new Date().toISOString(),
      nodeId: $node.id,
      workflowId: $workflow.id
    };
    
    console.log('Debug info:', debug);
    
    // 实际处理逻辑
    const result = processData($json);
    
    return {
      result,
      debug: $env.NODE_ENV === 'development' ? debug : undefined
    };
  })()
}}

表达式测试

javascript
// 创建测试用例
{{
  (() => {
    const testCases = [
      { input: { age: 25 }, expected: 'adult' },
      { input: { age: 16 }, expected: 'minor' },
      { input: { age: 70 }, expected: 'senior' }
    ];
    
    const categorizeAge = (age) => {
      if (age >= 65) return 'senior';
      if (age >= 18) return 'adult';
      return 'minor';
    };
    
    const results = testCases.map(test => ({
      ...test,
      actual: categorizeAge(test.input.age),
      passed: categorizeAge(test.input.age) === test.expected
    }));
    
    return {
      testResults: results,
      allPassed: results.every(r => r.passed),
      actualResult: categorizeAge($json.age)
    };
  })()
}}

实际应用案例

动态 API 端点

javascript
// 根据环境和用户类型构建 API URL
{{
  (() => {
    const baseUrl = $env.NODE_ENV === 'production' 
      ? 'https://api.example.com' 
      : 'http://localhost:3000';
    
    const version = $json.userType === 'premium' ? 'v2' : 'v1';
    const endpoint = $json.action || 'default';
    
    return `${baseUrl}/api/${version}/${endpoint}`;
  })()
}}

智能路由

javascript
// 基于多个条件的智能路由
{{
  (() => {
    const data = $json;
    const hour = new Date().getHours();
    
    // 紧急情况
    if (data.priority === 'urgent') {
      return 'urgent_queue';
    }
    
    // 工作时间
    if (hour >= 9 && hour <= 17) {
      if (data.type === 'technical') return 'tech_support';
      if (data.type === 'billing') return 'billing_team';
      return 'general_support';
    }
    
    // 非工作时间
    return 'after_hours_queue';
  })()
}}

小结

n8n 的变量和表达式系统是创建动态工作流的核心:

  1. 掌握基本语法:理解数据引用和表达式格式
  2. 熟练使用内置函数:字符串、数字、日期、数组操作
  3. 善用条件表达式:实现复杂的业务逻辑
  4. 优化性能:避免重复计算,合理使用缓存
  5. 调试和测试:确保表达式的正确性

下一篇文章,我们将学习定时任务和调度系统,这是自动化工作流的重要组成部分。

记住,强大的表达式系统需要谨慎使用。过于复杂的表达式会影响可读性和维护性,适当时候应该考虑使用 Code 节点来实现复杂逻辑。