LookMLで意図しないviewのオーバーライドを防ぐ方法
Refinementsを活用したLookMLの運用
このブログでは久しぶりなLooker関連の記事になります。
改めまして、弊社ではグループ各社で利用するためのBIツールとしてLookerを導入しております。
このLookerですが、LookMLと呼ばれるモデリング言語を用いて、データモデルを定義できる点が大きな強みかと思います。
今回はそんなLookMLに関するTipsになります。
Refinementsが役に立つシチュエーション
まず、LookMLをがっつり触っている方であれば、ご存知かとは思いますが、Refinementsと呼ばれる機能について簡単に触れておきたいと思います。
このRefinements(日本語訳では「絞り込み )ですが、簡単に言うと既存のviewまたはExploreを含むLookMLファイルを編集することなく、内容をオーバーライドできる機能になります。
この機能が役に立つシチュエーションですが、公式ドキュメントによると以下のような記述があります。
- 事前構築済みの LookML コンポーネントを使用する Looker Block を使用するプロジェクト
- 他のプロジェクトからファイルをインポートするプロジェクト
- データベースのテーブルからファイルを生成する必要があることが多いプロジェクト
- モデル間やプロジェクト間で LookML を共有しながら各々でカスタマイズを行う状況(ハブアンドスポーク構成)
弊社では特に3番目のシチュエーションで利用することが多く、データソースのテーブルを元にviewを作成して、そのファイルは編集せず、Refinementsを使用した先で手を加えるような運用になっております。
とは言っても、なかなかイメージし辛いかと思いますので、実際の挙動を確認してみたいと思います。
Refinementsの挙動の確認
例えば、下記のようなviewをテーブルから自動生成したとします。
view: item_master {
sql_table_name: `ec_site.item_master` ;;
dimension: item_id {
type: string
sql: ${TABLE}.item_id ;;
}
dimension: item_name {
type: string
sql: ${TABLE}.item_name ;;
}
dimension: item_price {
type: number
sql: ${TABLE}.item_price ;;
}
measure: count {
type: count
drill_fields: [item_name]
}
}
modelファイルでExploreを定義して、作成したviewを参照すると、Lookerでは以下のような表示になります。

この状態だと少し情報が足りないので、元のviewを直接編集したくなりますが、例えば元のテーブルのカラム構成が変わった時に、再度テーブルからviewを作成してしまうと、せっかく編集した内容が失われたり、元の内容の復元に手間がかかってしまいます。
そこで、以下のように元のviewに対して、Refinementsを使用した別のviewファイルを定義します。
ちなみにRefinementsを使用する際は、既存のviewの名前の前にプラス記号(+)を追加します。
include: "/base/item_master.view"
view: +item_master {
label: "商品マスタ"
dimension: item_id {
hidden: yes
label: "商品ID"
}
dimension: item_name {
label: "商品名"
}
dimension: item_price {
label: "商品価格"
}
measure: count {
label: "商品数"
}
}
このviewファイルで定義したviewを参照するとLookerでは、以下のような表示になります。

各ディメンションとメジャーにラベルが付与されて、商品ID( item_id )が見えなくなっています。
このように元のviewファイルを編集することなく、viewの内容をオーバーライドすることができました!
複数回Refinementsを使用したときの挙動
ここまでは、Refinementsの基本的な機能の簡単な説明となっており、この辺りはたくさん紹介されている記事があるため、今回はこのRefinementsに関する少しニッチめな機能の紹介をしたいと思います。
Lookerでは一つのviewに対して、複数回Refinementsを使用することができます。
つまり、以下のようにbase/item_master.viewに対してRefinementsを使用したrefinements/ref_item_master.viewを作成して、そこにRefinementsを使用したfinal_item_master.view を作成することができます。

なお、final_item_master.view の定義は以下のようになっており、ref_item_master.view ではhidden: yes となっていた商品ID( item_id )について、hidden: no としています。
include: "/refinements/ref_item_master.view"
view: +item_master {
dimension: item_id {
hidden: no
}
}
このときに、modelファイルでref_item_master.viewとfinal_item_master.view のどちらもincludeするようにしてみたいと思います。
connection: "item-db"
include: "/refinements/ref_item_master.view"
include: "/final_item_master.view"
explore: item_master {
label: "商品マスタ"
}
すると、先程hidden: yes となっていた商品ID( item_id )が見えるようになりました。

これはRefinementsの仕様として、include した順番にオーバーライドしていき、最後に読み込んだ内容が適用されるため、今回の場合は、ref_item_master.viewの後にfinal_item_master.view が読み込まれて、hidden: noが適用されたということになります。
予期せぬviewのオーバーライドを防ぐ方法
では、こういったときに、本来はrefinements 内で定義した内容はこれ以上変更して欲しくない場合、どうすれば良いでしょうか?
こういった際にはviewに設定できるパラメータであるfinal: yes が使えます。
これは、特定のRefinementsをviewやExploreの最終のRefinementsと見なすフラグになります。
先程、final_item_master.view によってオーバーライドされてしまったref_item_master.view にfinal: yes を設定してみたいと思います。
include: "/base/item_master.view"
view: +item_master {
final: yes
(中略)
}
するとfinal: yes が含まれるviewの後に、別のviewを読み込もうとしているため、以下のようにValidateの段階でエラーが出ます。

ちなみに以下のようにfinal: yes が含まれるviewのincludeを最後にするとエラーは出ません。
connection: "item-db"
include: "/final_item_master.view"
include: "/refinements/ref_item_master.view"
explore: item_master {
label: "商品マスタ"
}

このように、final: yes をviewに設定することでこれ以上内容が更新されなくなり、予期せぬオーバーライドを防ぐことができました!
まとめ
今回は、既存のviewまたはExploreを含むLookMLファイルを編集することなく、内容をオーバーライドできるRefinementsと呼ばれる機能の簡単な説明と、finalフラグを利用したTipsを紹介しました。
実際、今回のようなユースケースの場合は本来はextendsという機能を利用して、新たなviewを別名で定義するべきなのかもしれませんが、設定自体は非常にシンプルなので、思わぬ事故を防止するためにも、とりあえず設定しておくのでも良いかもしれません。
LookMLについては、まだまだ隠れた機能がたくさんあるかと思いますので、今後も皆様の役に立つような情報を積極的に発信できればと思います。
AUTHOR

朝日放送グループホールディングス株式会社 デジタル・アーキテック局 データ戦略チーム
グループ全体の統合的なデータ基盤の構築・データ分析の支援に従事している。 動画配信・テレビの視聴データ分析等で身につけた幅広い知識を活かして日々奮闘中!




