这是一个高级主题,假定您具备扎实的 LookML 知识。
概览
随着 LookML 模型的大小和复杂程度不断增加,在多个位置重复使用 LookML 变得越来越有用。借助 extends
参数,您可以重复使用代码,这有助于您执行以下操作:
- 编写 DRY(不重复)代码,以便在一个位置定义内容,使代码更加一致,修改速度更快
- 为不同用户管理不同的字段集
- 在项目的不同部分共享设计模式
- 在整个项目中重复使用联接、维度或测量集
如需扩展 LookML 对象,请创建新的 LookML 对象,然后添加 extends
参数以指示新对象是现有对象的扩展。这意味着您的项目将有两个版本的 LookML 对象。如果存在任何冲突,扩展对象的优先级更高,并覆盖要扩展对象的设置。如需了解详情,请参阅本页面后面的 extends
实现详情部分。
查看 LookML 优化结果:如果您需要拥有多个版本的视图或探索,则扩展视图或探索是理想之选。但如果您只是想修改视图或探索,而不修改包含该视图或探索的 LookML 文件,则可能需要改用优化。您还可以在优化中使用
extends
参数。如需了解详情和用例,请参阅 LookML 优化文档页面。
模型无法扩展,并且您不能将模型文件添加到其他模型文件中。不过,如果您想在多个模型中重复使用或扩展“探索”功能,则可以创建单独的“探索”文件,然后将该“探索”文件包含在模型文件中。
请参阅以下示例,了解如何扩展探索和扩展 LookML 信息中心。
扩展探索
以下是扩展“探索”的示例:
explore: customer {
persist_for: "12 hours"
}
explore: transaction {
extends: [customer]
persist_for: "5 minutes"
}
在本例中,我们创建了名为“客户”的探索,并创建了名为“交易”的第二个探索。Customer 中的所有内容(例如其联接)都将包含在 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 Additional 信息中心将包含 faa.dashboard.lookml
文件中定义的任何图块。此外,FAA Additional 信息中心将具有在其自己的 faa_additional.dashboard.lookml
文件中定义的任何功能块。
如需创建 LookML 信息中心,最简单的方法是从用户定义的信息中心获取 LookML。您还可以使用此方法获取各个信息中心图块的 LookML。如果您使用的是此方法,请务必确保图块的位置不重叠。在上面的示例中,图块都位于信息中心的顶行,由 row: 0
指示:
文件:faa.dashboard.lookml
row: 0
col: 0
width: 8
height: 6
不过,我们在 FAA Additional 信息中心内添加的新图块位于 col: 8
中,因此它会显示在扩展信息中心内的图块旁边:
文件:faa_additional.dashboard.lookml
row: 0
col: 8
width: 8
height: 6
这些元素位于不同的信息中心文件中,因此很容易被忽视。因此,如果您向扩展仪表板添加图块,请务必检查扩展仪表板中的图块与扩展仪表板中的图块之间是否存在定位冲突。
需要延期
您可以使用 extension: required
参数将 LookML 对象标记为需要扩展,这意味着无法单独使用该对象。具有 extension: required
的对象本身对用户不可见;它仅用作通过其他 LookML 对象扩展的起点。探索、视图和 LookML 信息中心均支持 extension
参数。
包含 extension: required
的 explore
不能用作数据测试的 explore_source
。LookML 验证器将生成一条错误,指出找不到 explore_source
。
使用元数据查看对象的扩展
您可以点击 Looker IDE 中的 explore
或 view
参数,然后使用元数据面板查看对象的任何扩展程序,或扩展的对象。如需了解相关信息,请参阅 LookML 对象的元数据文档页面。
extends
的实现详情
以下是 Looker 在扩展 LookML 对象时采取的步骤:
- 复制正在扩展的对象:Looker 会为正在扩展的视图、探索或 LookML 信息中心创建 LookML 的副本。这个新副本是扩展对象。
- 合并两个副本的 LookML:Looker 会将扩展对象的 LookML 合并到扩展对象中。
- 解决副本之间的冲突:在大多数情况下,如果扩展对象和扩展对象中都定义了 LookML 元素,则使用扩展对象中的版本。不过,在其他情况下,扩展程序会合并参数值,而不是替换这些值。有关信息,请参阅本页面中的组合参数部分。
- 应用 LookML:所有冲突解决后,Looker 都会使用标准逻辑解释生成的 LookML。换言之,与任何其他视图、探索或 LookML 信息中心一样,Looker 将使用所有标准默认值和假设。
以下各部分以扩展视图为例,介绍了这些步骤的具体内容。以下是基础视图(即 User 视图)的 LookML:
view: user {
suggestions: yes
dimension: name {
sql: ${TABLE}.name ;;
}
dimension: status {
sql: ${TABLE}.status ;;
type: number
}
}
以下是用于扩展 User 视图的 User with Age Extensions 视图的 LookML:
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
和include
参数。 - 在扩展探索时,我们会添加
view_name
和view_label
参数。
在此特定示例中,我们未将 sql_table_name
添加到 User 视图,这会导致下一步中出现一些问题。
第 4 步:照常解读 LookML
在最后一步中,生成的 LookML 被解释为正常值,包括所有默认值。在此特定示例中,生成的视图 LookML 将解读如下:
include: "/views/user.view"
view: user_with_age_extensions {
suggestions: no
dimension: age {
type: number
sql: ${TABLE}.age ;;
}
dimension: name {
sql: ${TABLE}.name ;;
}
dimension: status {
sql: ${TABLE}.status ;;
type: string
}
}
请注意,生成的 LookML 包含 view: user_with_age_extensions
,但不包含 sql_table_name
参数。因此,Looker 会假设 sql_table_name
的值等于视图名称。
问题在于,我们的数据库中可能没有名为 user_with_age_extensions
的表。因此,我们需要向将扩展的任何视图添加 sql_table_name
参数。将 view_name
和 view_label
添加到将扩展的探索可以避免类似问题。
合并扩展
您可以通过以下几种方式通过扩展利用 LookML 对象:
- 一个对象可以扩展多个其他对象。
- 扩展对象本身可以扩展。
- 可以在优化中使用扩展(如需了解详情,请参阅 LookML 优化文档页面)。
如需查看高级用例的示例并阅读问题排查提示,请参阅对高级
extends
用例示例进行问题排查“最佳做法”页面。
同时扩展多个对象
您可以同时扩展多个信息中心、视图或探索。例如:
explore: orders {
extends: [user_info, marketing_info]
}
# Also works for dashboards and views
延期流程的工作原理与实现示例中所述的完全相同,但对于如何解决冲突,还有一条额外的规则。如果 extends
参数中列出的多项内容之间存在冲突,系统会优先考虑最后列出的项。因此,在上面的示例中,如果 user_info
和 marketing_info
之间存在冲突,则 marketing_info
探索胜出。
将多个扩展链接在一起
您还可以根据需要将任意数量的扩展链接在一起。例如:
explore: orders {
extends: [user_info]
...
}
explore: user_info {
extends: [marketing_info]
...
}
同样,扩展流程的工作原理与实现示例中所述的完全相同,但有一条与解决冲突相关的额外规则。如果存在任何冲突,则会将优先级分配给扩展链中的最后一项。在此示例中:
orders
的优先级高于user_info
和marketing_info
。user_info
的优先级将高于marketing_info
。
组合参数
在大多数情况下,如果扩展对象和扩展对象中都定义了 LookML 元素,则将使用扩展对象中的版本。本页的实现示例就是这种情况。
但在以下情况下,扩展会合并参数值,而不是覆盖这些值:combine
- 对于 additive 参数
- 使用
EXTENDED*
列表关键字 - 使用
sql
参数的${EXTENDED}
关键字
某些参数可以累加
在许多情况下,如果扩展对象包含的参数与扩展对象相同,则扩展对象的值会覆盖扩展对象的参数值。但对于某些参数,扩展可以累加,也就是说,来自扩展对象的值会与扩展对象中的值结合使用。
以下参数可累加:
对于维度和测量:
对于参数:
对于派生表:
对于观看次数:
对于探索:
在以下示例中,carriers
视图有一个带有 link
参数的 name
维度:
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
视图还有一个 name
维度,该维度在 link
参数中具有不同的设置:
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
中的定义,因为它会执行扩展。
不过,如果您愿意,也可以选择combine这些定义。为此,您需要使用 ${EXTENDED}
关键字,如下所示:
view: product_short_descriptions {
extends: products
dimension: description {
sql: LEFT(${EXTENDED}, 50) ;;
}
}
view: products {
dimension: description {
sql: ${TABLE}.full_description ;;
}
}
现在,我们将以不同的方式处理 sql
参数的冲突。它不会取胜 product_short_descriptions
定义,而是从 products
获取定义并将其插入使用 ${EXTENDED}
的位置。在本例中,生成的 description
定义为:LEFT(${TABLE}.full_description, 50)
。
注意事项
已进行本地化的项目
扩展对象时,请注意本地化规则也适用于您的扩展。如果您要扩展对象,然后定义新的标签或说明,则应在项目的语言区域字符串文件中提供本地化定义。如需了解详情,请参阅将 LookML 模型本地化文档页面。