通过扩展重复使用代码

这是一个高级主题,假定读者具备充分的 LookML 知识。

概览

随着 LookML 模型的大小和复杂性不断增加,在多个位置重复使用 LookML 变得越来越实用。您可以使用 extends 参数重复使用代码,这有助于您执行以下操作:

  • 编写 DRY(不要自行重复)代码,这样您就可以在一个位置定义内容,使代码更一致且更快速修改
  • 为不同的用户管理不同的字段集
  • 在项目的不同部分共享设计模式
  • 在整个项目中重复使用多组联接、维度或测量值

如需扩展 LookML 对象,您需要创建一个新的 LookML 对象,然后添加 extends 参数来指明新对象是现有对象的扩展。这意味着您的项目将有两个版本的 LookML 对象。如有任何冲突,以扩展对象为准,并覆盖要扩展对象的设置。如需了解详情,请参阅本页面后面部分中的 extends 实现细节部分。

查看 LookML 优化。
如果您想拥有多个版本的视图或“探索”,那么扩展视图或“探索”非常适合。但是,如果您只是想修改视图或探索,而不修改包含视图的 LookML 文件,您可能需要改用优化过滤器。您还可以在优化中使用 extends 参数。如需了解详情和用例,请参阅 LookML 优化文档页面。

您可以扩展视图、“探索”和 LookML 信息中心:

不能扩展模型,并且不能将模型文件添加到其他模型文件中。相反,如果您想在多个模型中重复使用或扩展“探索”,则可以创建单独的探索文件,然后将该探索文件添加到模型文件中

请参阅以下示例,了解如何扩展“探索”专区扩展 LookML 信息中心

扩展探索

以下是扩展“探索”的示例:

explore: customer {
  persist_for: "12 hours"
}

explore: transaction {
  extends: [customer]
  persist_for: "5 minutes"
}

在此示例中,我们创建了名为 Customer 的探索,并创建了名为“事务”的第二个探索。Customer 中的所有内容(例如联接),都将包含在 Transaction 中。Transaction 中的所有内容都会保留在 Transaction 中。

但要注意存在冲突情况:客户“探索”工具显示 persist_for 设置应该为 12 小时,而交易“探索”设置显示应为 5 分钟。对于交易“探索”,系统将使用 persist_for: "5 minutes" 设置,因为它会覆盖“探索”扩展程序中的相应设置。

扩展 LookML 信息中心

如需扩展 LookML 信息中心,扩展信息中心和扩展信息中心必须包含在模型文件中。如果使用 extends 参数的信息中心包含在没有扩展基准信息中心的模型文件中,您会收到 LookML 验证错误消息,指出找不到基本信息中心(以及其他错误)。

下面是一个信息中心文件示例:

文件:faa.dashboard.lookml

- dashboard: faa
  title: FAA Dashboard
  layout: newspaper
  elements:
  - title: Aircraft Location
    name: Aircraft Location
    model: e_faa
    explore: aircraft
    type: looker_map
    fields:
    - aircraft.zip
    - aircraft.count
    sorts:
    - aircraft.count desc
    limit: 500
    query_timezone: America/Los_Angeles
    series_types: {}
    row: 0
    col: 0
    width: 8
    height: 6

我们可以创建一个新的 LookML 信息中心文件,并通过添加新图块来扩展 FAA 信息中心:

文件:faa_additional.dashboard.lookml

- dashboard: faa_additional
  title: FAA Additional
  extends: faa
  elements:
  - title: Elevation Count
    name: Elevation Count
    model: e_faa
    explore: airports
    type: looker_scatter
    fields:
    - airports.elevation
    - airports.count
    sorts:
    - airports.count desc
    limit: 500
    query_timezone: America/Los_Angeles
    row: 0
    col: 8
    width: 8
    height: 6

由于 FAA 信息中心扩展了 FAA 信息中心,因此它包含 faa.dashboard.lookml 文件中定义的所有图块。此外,FAA 附加信息中心还会在自己的 faa_additional.dashboard.lookml 文件中定义任何图块。

创建 LookML 信息中心的最简单方法是从用户定义的信息中心获取 LookML。您还可以使用此方法获取各个信息中心图块的 LookML。如果使用此方法,请确保图块的位置不重叠。在上面的示例中,图块都位于信息中心的第一行,由 row: 0 表示:

文件:faa.dashboard.lookml


    row: 0
    col: 0
    width: 8
    height: 6

不过,我们即将在 FAA 额外信息中心内增加的新图块位于 col: 8,因此它会显示在“扩展后的”信息中心内的相应图块旁边:

文件:faa_additional.dashboard.lookml


    row: 0
    col: 8
    width: 8
    height: 6

这很容易错过,因为这些元素位于不同的信息中心文件中。因此,如果您要向扩展的信息中心添加图块,请务必检查扩展信息中心内的图块与扩展信息中心内的图块之间的位置冲突。

需要使用扩展程序

您可以使用 extension: required 参数将 LookML 对象标记为需要扩展,这意味着对象无法单独使用。包含 extension: required 的对象本身对用户不可见;它仅充当一个由其他 LookML 对象扩展的起点。探索视图LookML 信息中心支持 extension 参数。

带有 extension: requiredexplore 不能用作数据测试explore_sourceLookML 验证器将生成一个错误,指出找不到 explore_source

使用元数据查看对象的扩展程序

您可以在 Looker IDE 中点击 exploreview 参数,然后使用元数据面板查看对象上的所有扩展,或查看对象扩展的对象。如需了解详情,请参阅 LookML 对象的元数据文档页面。

extends 的实现详情

扩展 LookML 对象时,Looker 会执行以下步骤:

  1. 复制要扩展的对象:Looker 为要扩展的视图、探索或 LookML 信息中心创建 LookML 的副本。这一新副本是 extensioning 对象。
  2. 合并两个副本的 LookML:Looker 会将扩展的 对象的 LookML 合并到扩展对象中。
  3. 解决副本之间的冲突:在大多数情况下,如果扩展对象和扩展对象中都定义了 LookML 元素,则系统会使用扩展对象中的版本。不过,在其他情况下,扩展程序会组合参数值而非替换这些值。如需了解详情,请参阅本页面中的组合参数部分。
  4. 应用 LookML:解决所有冲突后,Looker 会使用标准逻辑解释生成的 LookML。换言之,与任何其他视图、探索或 LookML 信息中心一样,Looker 会使用所有标准默认值和假设。

下面几部分将具体介绍这些步骤,并以视图为例进行扩展。基本视图(即 User 视图)的 LookML 如下所示:

view: user {
  suggestions: yes

  dimension: name {
    sql: ${TABLE}.name ;;

  }
  dimension: status {
    sql: ${TABLE}.status ;;
    type: number
  }
}

下面是 User with Age Extensions 视图的 LookML,扩展了 User 视图:

include: "/views/user.view"

view: user_with_age_extensions {
  extends: [user]
  suggestions: no

  dimension: age {
    type: number
    sql: ${TABLE}.age ;;
  }

  dimension: status {
    type: string
  }
}

第 1 步:复制 LookML

在本例中,user 视图扩展为 user_with_age_extensions 视图。由于 user 是正在扩展的视图,因此会在合并前创建其副本。在此处制作副本并非特别重要;了解原始 user 视图保持不变且可照常使用这一事实非常重要。

第 2 步:合并副本

下一步是将扩展 视图 (user) 中的所有 LookML 合并到扩展 视图 (user_with_age_extensions) 中。了解此合并的性质非常重要,它只是 LookML 对象的合并。实际上,这意味着合并了任何显式写入的 LookML,但您尚未记录的默认 LookML 值不会合并。从某种意义上说,这只是 LookML 组合在一起的那些文本,而这些文本没有任何意义。

第 3 步:解决冲突

第三步是解决合并的视图之间的冲突。

在大多数情况下,如果扩展对象和扩展对象中均定义了 LookML 元素,系统会使用扩展对象中的版本。不过,在其他情况下,扩展程序会组合参数值而非替换这些值。如需了解详情,请参阅本页面中的组合参数部分。

user_with_age_extensions 示例为例,由于所有参数均不是累加参数,且未指定任何特殊列表选项或 sql 关键字,因此扩展视图中的参数值将会替换扩展视图中的参数值:

  • 扩展视图名称 (user_with_age_extensions) 会替换扩展视图名称 (user)。
  • suggestions: no 的扩展 值会替换扩展后的 suggestions: yes
  • 扩展视图有一个名为 age 的维度,该维度不存在于扩展视图(无冲突)。
  • 扩展视图包含一个名为 name 的维度,该维度在扩展视图中不存在(无冲突)。
  • 扩展视图中的 status 维度 type: string 值会替换扩展后的视图中的 type: number 值。
  • status”维度有一个 sql 参数,该参数在扩展视图中不存在(无冲突)。

系统尚未考虑使用默认的 LookML 值,因为您不想错误地认为默认值之间的冲突正在得到解决。实际上,在这一步中,它们只是被忽略了。这就是我们在扩展对象时需要明确添加额外参数的原因:

在此特定示例中,我们用户视图添加sql_table_name,此视图将导致下一步中的一些问题。

第 4 步:照常解读 LookML

在最后一步中,生成的 LookML 会照常解读,包括所有默认值。在此特定示例中,我们最终看到的 LookML 包含 view: user_with_age_extensions,但不包含 sql_table_name 参数。因此,Looker 会假定 sql_table_name 的值等于视图名称:

问题在于,我们的数据库中可能没有名为 user_with_age_extensions 的表。因此,我们需要向将要扩展的任何视图添加 sql_table_name 参数。为“探索”功能添加将延长的 view_nameview_label 可避免类似问题。

组合扩展

您可以通过以下几种方式使用具有扩展功能的 LookML 对象:

如需查看高级用例的示例并阅读问题排查提示,请参阅帮助中心文章:高级 extends 用例示例问题排查

同时扩展多个对象

您可以同时扩展多个信息中心、数据视图或探索。例如:

explore: orders {
  extends: [user_info, marketing_info]
}
# Also works for dashboards and views

该扩展过程与实现示例中描述的完全相同,但还有一条关于冲突解决方式的额外规则。如果 extends 参数中列出的多个项之间存在任何冲突,系统会优先考虑最后列出的项。因此,在上面的示例中,如果 user_infomarketing_info 之间存在冲突,marketing_info 探索就会胜出。

将多个扩展链接在一起

您还可以根据需要将任意数量的附加信息链接起来。例如:

explore: orders {
  extends: [user_info]
  ...
}
explore: user_info {
  extends: [marketing_info]
  ...
}

同样,扩展过程的工作原理也与实现示例完全相同,但还额外规定了冲突解决规则。如果存在冲突,系统会优先考虑扩展链中的最后一个项。在此示例中:

  • orders 的优先级将高于 user_infomarketing_info
  • user_info 的优先级高于 marketing_info

组合参数

在大多数情况下,如果扩展对象和扩展对象中均定义了 LookML 元素,系统会使用扩展对象中的版本。本页中的实现示例就属于这种情况。

不过,在以下情况下,扩展程序会合并参数值,而不是替换这些值:

部分参数可累加

在许多情况下,如果扩展对象与要扩展的对象包含相同的参数,则扩展对象的值会覆盖扩展对象的参数值。但对于某些参数,扩展可以累加,这意味着扩展对象中的值会与扩展对象中的值配合使用。

以下参数可添加

在以下示例中,carriers 视图的 name 维度带有 link 形参:

view: carriers {
  sql_table_name: flightstats.carriers ;;

  dimension: name {
    sql: ${TABLE}.name ;;
    type: string
    link: {
      label: "Google {{ value }}"
      url: "http://www.google.com/search?q={{ value }}"
      icon_url: "http://google.com/favicon.ico"
    }
  }
}

下面是扩展 carriers 视图的 carriers_extended 视图。carriers_extended 视图的 link 参数中也有一个 name 维度,分别具有不同的设置:


include: "/views/carriers.view.lkml"

view: carriers_extended {
  extends: [carriers]

  dimension: name {
    sql: ${TABLE}.name ;;
    type: string
    link: {
      label: "Dashboard for {{ value }}"
      url: "https://docsexamples.dev.looker.com/dashboards/307?Carrier={{ value }}"
      icon_url: "https://www.looker.com/favicon.ico"
    }
  }
}

carriers_extended 视图中,这两个 link 形参是相加的,因此 name 维度会同时包含这两个链接。“探索”中的维度如下所示:

列表的其他选项

在处理列表时,您可以选择组合这些列表,而不是扩展对象列表。请参考下面这个名为 animals 的冲突列表的简单扩展程序:

view: pets {
  extends: fish
  set: animals {
    fields: [dog, cat]
  }
}
view: fish {
  set: animals {
    fields: [goldfish, guppy]
  }
}

在本例中,pets 视图正在执行扩展操作,因此会胜出,使得 animals 包含 [dog, cat]。不过,利用特殊的 EXTENDED* 集,您可以改为组合列表:

view: pets {
  extends: fish
  set: animals {
    fields: [dog, cat, EXTENDED*]
  }
}
view: fish {
  set: animals {
    fields: [goldfish, guppy]
  }
}

现在,animals 列表将包含 [dog, cat, goldfish, guppy]

在冲突解决期间合并而不是替换

在大多数情况下,如果扩展过程中出现任何冲突,以扩展对象为准。以下面的简单扩展程序为例:

view: product_short_descriptions {
  extends: products
  dimension: description {
    sql: ${TABLE}.short_description ;;
  }
}
view: products {
  dimension: description {
    sql: ${TABLE}.full_description ;;
  }
}

您可以看到,description 维度中的 sql 参数存在冲突。通常,product_short_descriptions 中的定义只是覆盖 products 中的定义,因为它正在进行扩展。

不过,如果您愿意,也可以选择组合定义。为此,您需要使用 ${EXTENDED} 关键字,如下所示:

view: product_short_descriptions {
  extends: products
  dimension: description {
    sql: LEFT(${EXTENDED}, 50) ;;
  }
}
view: products {
  dimension: description {
    sql: ${TABLE}.full_description ;;
  }
}

现在,系统会以不同的方式解决 sql 参数的冲突。系统会从 products 获取定义并将其插入使用 ${EXTENDED} 的位置,而不是在 product_short_descriptions 定义中胜出。在本示例中,生成的 description 定义为:LEFT(${TABLE}.full_description, 50)

注意事项

本地化的项目

扩展对象时,请注意本地化规则也适用于您的扩展。如果您要扩展对象,然后定义新的标签或说明,则应在项目的语言区域字符串文件中提供本地化定义。如需了解详情,请参阅本地化 LookML 模型文档页面。