错误:未知或无法访问的字段

当您处理 LookML 文件并对更新感到满意后,部署 LookML 更改的下一步是运行 LookML 验证器以执行完整的模型验证。

有时,您可能会看到如下错误:

 Unknown or inaccessible field "user_order_facts.lifetime_orders" referenced in "users.lifetime_orders". Check for typos and missing joins.

在此示例中,错误是指 users 视图中的 lifetime_orders 字段。此错误表示 users.lifetime_orders 无法访问其引用的 user_order_facts.lifetime_orders 字段。

调试树

请使用以下决策树排查常见的 Liquid 问题:

以下部分将更详细地介绍树中的场景。

为什么会发生此错误?

此错误可能是由以下几种原因导致的:

  1. 您引用的字段不存在
  2. 您引用的字段是整个维度组 - 例如,引用的维度组未附加timeframe
  3. 某些探索无法访问该字段,因为缺少联接

相应字段不存在

如果 LookML 字段中引用了 user_order_facts.lifetime_orders 字段,但该字段本身不存在,您将收到 unknown or inaccessible field 错误。

您可以通过将触发错误的字段(在本例中为 user_order_facts.lifetime_orders)添加到包含相关字段的视图中来解决此错误。在这种情况下,您可以确保该字段已在 user_order_facts 视图中定义;如果不存在,您可以添加该字段。

该字段引用整个维度组

维度组表示一组维度。type: time 维度组表示在 timeframe 参数中定义的一组时间段维度。在 LookML 中引用维度组时,您必须在维度组名称后附加相应的维度(在本例中为 timeframe)。

例如,请考虑以下维度组:

  dimension_group: created {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.created_at ;;
  }

如果您想在其他 LookML 字段中引用 created 维度组,则必须引用该组中的特定时间范围维度,例如以下维度之一:

  • date${created_date}
  • week${created_week}
  • month${created_month}

如果您尝试仅使用维度组的名称(即 ${created}),Looker 将不知道您指的是哪个时间范围,并会生成错误。

缺少联接

以下是 users.lifetime_orders 的 LookML 定义:

  dimension: lifetime_orders {
    type: number
    sql: ${user_order_facts.lifetime_orders};;
  }
请注意,我们使用替换运算符 ${} 来引用 LookML 字段 user_order_facts.lifetime_orders

users 视图中的 lifetime_orders 维度引用了 user_order_facts 视图中的 lifetime_orders 字段。在这种情况下,之所以会触发错误,是因为模型文件中存在以下实例:users 视图已联接到探索,但 user_order_facts 尚未联接。

如需查看哪些探索导致了问题,您可以展开错误消息中突出显示的发生次数:

扩展的错误消息,显示了两个原因(users:79 [ecommerce:order_items] 和 users:79 [ecommerce:orders])的查看次数、查看代码行数和探索。

这些出现次数表明,ecommerce 模型中的 order_itemsorders 探索导致了该错误。这些探索具有许多联接,并在模型文件中定义如下:

  explore: orders {
    join: users { # users joined without user_order_facts
      relationship: many_to_one
      sql_on: ${orders.user_id} = ${users.id}
    }
  }

  explore: order_items {
    join: inventory_items {
      relationship: many_to_one
      sql_on: ${order_items.inventory_item_id} = ${inventory_items.id}
    }
    join: orders {
      relationship: many_to_one
      sql_on: ${order_items.order_id} = ${orders.id}
    }
    join: users { # users joined without user_order_facts
      relationship: many_to_one
      sql_on: ${orders.user_id} = ${users.id}
    }
  }

在这两个探索中,users 视图在联接时同时联接 user_order_facts 视图;因此,这两个探索都无法访问 user_order_facts.lifetime_orders 字段。如果您尝试在任一探索中查询引用 user_order_facts.lifetime_ordersusers.lifetime_orders 字段,则会触发错误。

LookML 验证器会警告您,用户在查询 users_order_facts.lifetime_orders 时会收到错误。如果探索中还加入了 user_order_facts,则 users.lifetime_orders 字段不会触发错误。

例如,请考虑 users 探索:

  explore: users {
    join: user_order_facts {
      sql_on: ${users.id} = ${user_order_facts.users_id}
    }
  }

此处联接了 user_order_facts ,因此查询 users.lifetime_orders 不会触发错误。

如何修复因缺少联接而导致的错误?

如果此错误是由缺少联接引起的,您可以通过以下几种方式来修正此错误:

  1. 所有支持请求中加入缺失的视图。对于本页中使用的示例,请确保在“探索”中联接 users 视图的任何位置都联接 user_order_facts 视图。
  2. 如果您不想加入缺失的视图,请从探索中排除导致错误的字段。

加入缺失的视图

在上述示例中,可以通过将 user_order_facts 与也联接了 users 的所有探索联接来解决此错误。这样可确保在查询中使用 users.lifetime_orders 时,“探索”可以访问 user_order_facts.lifetime_orders

您可以使用 IDE 中的元数据面板查看使用 users 视图的所有 Explore。

以下示例联接了缺失的视图:

  explore: order_items {
    join: inventory_items {
      relationship: many_to_one
      sql_on: ${inventory_items.id} = ${order_items.inventory_item_id}
    }
    join: orders {
      relationship: many_to_one
      sql_on: ${order_items.order_id} = ${orders.id}
    }
    join: users {
      relationship: many_to_one
      sql_on: ${orders.user_id} = ${users.id}
    }
    join: user_order_facts { # join user_order_facts through users
      relationship: many_to_one
      sql_on: ${users.id} = ${user_order_facts.users_id}
    }
  }

现在,如果您重新运行 LookML 验证程序,此错误应该不会再出现。

从探索中排除导致错误的字段

您可能不想将 user_order_facts 视图联接到所有联接了 users 的探索。例如,您可能不希望用户在 orders 探索中访问 user_order_facts 视图中的字段,但希望用户能够毫无错误地访问 users 视图中的字段。为此,您可以从 orders 探索中排除导致错误的字段 users.lifetime_orders,方法是使用 fields 参数。

借助探索的 fields 参数,您可以包含或排除探索中的特定字段。在这种情况下,您可以从 orders 探索中排除 users.lifetime_orders 字段,如下所示:

  explore: orders {
    fields: [-users.lifetime_orders] # exclude users.lifetime_orders
    join: users {
      relationship: many_to_one
      sql_on: ${orders.user_id} = ${users.id}
    }
  }