📚

VizQL Data Service APIを使ってTableau Cloudにパブリッシュされているデータの情報を外部から参照してみた

2024/10/21に公開

カスタマーサクセスマネージャー見習いの玉井です。

皆さんはTableauのVizQL Data Service APIをご存知でしょうか?

https://www.tableau.com/blog/vizql-data-service-beyond-visualizations

VizQL Data Service APIとは

簡単にいうと、Tableau Cloud(またはTableau Server)にパブリッシュされているデータソースに対して、外部からアクセスできるAPIです。

これまでは、Tableau CloudやTableau Serverにパブリッシュされているデータソース(PDS)にアクセスするためには、Tableau DesktopやWeb編集機能等、「何らかのTableau製品」を使用する必要がありました(当たり前って感じですが)。しかし、前述の通り、VizQL Data Service APIを使うことで、Tableau外部から、PDSにアクセスできるようになりました。

何が嬉しいのかって話ですが、APIである以上、プログラミングされた定期処理や、Webアプリケーション等に、PDSを組み込むことができます。例えば、今年のTableau Conferenceでは、Apple Watch(のアプリ)に、PDSのデータを表示するように開発している模様が発表されています(以下動画の1時間35分あたりをご覧ください。スクショは流石に怒られそうなので自粛)。

https://www.salesforce.com/plus/experience/tableau_conference_2024/series/tableau_conference_2024_highlights/episode/episode-s1e3

つまり、PDSを、Tableauだけでなく、あらゆる場所で活用できるようになります。

VizQL Data Service APIの状況

今年のTableau Conference 2024で発表され、開発者プレビュー版が既に登場済ですが、試用するためには、デベロッパープログラムに登録し、それ専用の環境でないと試すことができない状態でした。

しかし、この度、Tableau 2024.3のリリースに合わせて、開発者プレビューがパワーアップし、(Tableau Cloudについては)自分の環境でも試用できるようになりました。

https://www.tableau.com/blog/use-vizql-data-service-tableau-cloud-site

というわけで、自分のTableau Cloudで、VizQL Data Service APIを試してみたいと思います。

やってみた

今回は、PDSのメタデータを取得できるReadMetadataを試してみたいと思います。

https://help.tableau.com/current/api/vizql-data-service/en-us/reference/index.html#tag/ReadMetadata

当記事は作業した順にダラダラ書いていきます。もう少しまとまった情報をシュッと確認したい場合は、下記の公式ドキュメントをご覧ください。

https://help.tableau.com/current/api/vizql-data-service/en-us/docs/whats_new.html

環境

  • Tableau Cloud 2024.3
  • Apple M1 Pro
    • macOS Sonoma 14.7

個人用アクセストークン(PAT)を発行する

今回はPATを用いてAPI利用時の認証を行うため、先にPATを発行しておきます。

Tableau Cloudにログインし、マイアカウント設定ページに行って…

個人用アクセストークンの項から、新規トークンを発行します。トークン自体はここでしっかりとメモっておきましょう。

Credential Tokenを取得する

ReadMetadataを叩く際、「正式なデータソースの名前」を指定する必要があります。ドキュメントによれば、Tableau CloudのUI上でも分かるようですが、折角なので(?)、Tableau REST APIのQuery Data Sourcesを叩いてデータソース名を取得しようと思います。
んで、Tableau REST APIを叩くには、Credential Tokenが必要なので、まずはそれを取得します。

事前にsignin.xmlを作成しておきます(PATの情報等を記載しておく)。

signin.xml
<tsRequest>
    <credentials
      personalAccessTokenName="<PATの名前>" personalAccessTokenSecret="<PAT本体の文字列>" >
          <site contentUrl="サイトID" />
    </credentials>
</tsRequest>

xmlファイルが準備できたら、叩きます。

$ curl "https://10az.online.tableau.com/api/3.24/auth/signin" -X POST -d @signin.xml

以下の通り、credentials tokenが取得できました。メモっておきます。

レスポンス
<?xml version="1.0" encoding="UTF-8"?>
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api https://help.tableau.com/samples/en-us/rest_api/ts-api_3_24.xsd">
  <credentials token="xxxxxxxxxxxxxxxx" estimatedTimeToExpiration="179:20:26">
    <site id="xxxxxxxxxxxxxxx" contentUrl="xxxxxxx"/>
    <user id="xxxxxxxxxxxxxxx"/>
  </credentials>
</tsResponse>

(VizQL Data Serviceでアクセスしたい)データソースの正式名称を取得する

Credential Tokenが取得できたので、これを使ってQuery Data Sourcesを叩き、データソースの正式名称を取得します。

$ curl https://10az.online.tableau.com/api/3.24/sites/<さっき取得したsite id>/datasources -X GET -H "X-Tableau-Auth:<さっき取得したcredentials token>"

Tableau CloudのPDSの情報がザーッと取得できますので、お目当てのデータソースの名前を確認しましょう。今回は以下のデータソースにします。

レスポンス
(一部省略)
<datasource contentUrl="tamade_store_list" createdAt="2024-08-01T07:54:06Z" description="" encryptExtracts="false" hasExtracts="false" id="a8d66f3b-2ae0-40a0-b3f2-fb0a37924f13" isCertified="false" name="tamade_store_list 抽出" size="1" type="hyper" updatedAt="2024-08-01T07:54:07Z" useRemoteQueryAgent="false" webpageUrl="xxxx">
(一部省略)

contentUrlの後に続いている値が正式名称となりますので、上記の場合はtamade_store_listが正式名称となります。

ReadMetadataを叩いてみる

事前準備が色々とありましたが、やっとVizQL Data Service APIを叩くフェーズに来ました。というわけで、以下を実行してみます。

ちなみに、間違いやすいのですが、ここで指定する2つの値(Credential-KeyとCredential-Value)は、Credential Tokenではなく、最初に取得しているPATの方を使います。

$ curl --location 'https://developer.salesforce.com/tools/tableau/headless-bi/v1/read-metadata' \
--header 'Credential-Key: <PATの名前>' \
--header 'Credential-Value: <PAT本体の文字列>' \
--header 'Content-Type: application/json' \
--data '{
    "connection": {
      "tableauServerName": "10az.online.tableau.com",
      "siteId": "xxxxxxxx",
      "datasource": "tamade_store_list"
    }
}'

ここでちょっと話が脱線しますが、URLについて注目です。Tableau REST APIとはドメイン名から全然違います。完全ド新規に開発された機能っぽさが伺えますね(適当な感想)。また、headless-biという文字列が入っているのも要注目ポイントではないでしょうか(後でまた説明します)。

(あと、ついにレスポンスがxmlじゃなくてjsonになってます!うおおおおお!!!)

上記を実行すると、以下の結果が取得できました!Tableau Cloudにパブリッシュされているデータソースtamade_store_listの各フィールドに関するデータが取得できています。

上記リクエストに対するレスポンス
{
	"data" : [
		{
			"columnName" : "MapFan住所",
			"caption" : "MapFan住所",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "MapFan経度",
			"caption" : "MapFan経度",
			"dataType" : "REAL",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "MapFan緯度",
			"caption" : "MapFan緯度",
			"dataType" : "REAL",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "Number of Records",
			"caption" : "Number of Records",
			"dataType" : "INTEGER",
			"columnContainsNulls" : true,
			"objectGraphId" : ""
		},
		{
			"columnName" : "マッチングフラグ",
			"caption" : "マッチングフラグ",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "マッチング数",
			"caption" : "マッチング数",
			"dataType" : "REAL",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "マッチング精度",
			"caption" : "マッチング精度",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "住所",
			"caption" : "住所",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "営業時間",
			"caption" : "営業時間",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "地区",
			"caption" : "地区",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "外貨両替機設置店",
			"caption" : "外貨両替機設置店",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "店舗名",
			"caption" : "店舗名",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "通し番号",
			"caption" : "通し番号",
			"dataType" : "INTEGER",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		},
		{
			"columnName" : "電話番号",
			"caption" : "電話番号",
			"dataType" : "STRING",
			"columnContainsNulls" : true,
			"objectGraphId" : "Migrated Data"
		}
	]
	}%

上記のメタデータが正しいものかどうか、実際にTableau Cloud上で確認してみます。

間違いなく取得できております。

おわりに

今回はPDSのメタデータを取得しただけですが、どちらかというともう一つのエンドポイントであるQueryDatasourceの方が目玉だと思うので、そちらも試してみたいですね(Tableau Cloud外からPDSに対してクエリを実行できる)。

headless-biについて

前述したように、VizQL Data Service APIのURLにはheadless-biという文字が入っています。これは一体何でしょうか?

headless-bi(ヘッドレスBI)とは、「ユーザーインターフェース(UI)を持たないBIツール」のことを指します。

通常のBIツールは、データの可視化やレポート作成のためのダッシュボードやグラフなどのUIを提供しますが、ヘッドレスBIはこれらのUIを持たず、データの分析機能等をAPIを通じて提供するものです。詳しくは以下の記事がわかりやすいと思います。

https://zenn.dev/churadata/articles/e779a733c5fb35

例えば、Google Cloud社のLookerなんかは、以前からこういった機能を持っています。Tableauは、どちらかというと、ビジュアライズ機能に特化しており、こういう技術者寄りの機能はあんまり優先しないイメージでした。

しかし、VizQL Data Service APIのURLにはheadless-biの文字が刻まれており、これからのTableauはこういう方面にも力を入れていくメッセージを感じることができますね…!(これは私個人の感想であり、もしかしたらGAした際にはURLごとめっちゃ違うものに変わってる可能性も十分にあります)。

ですので、個人的には正式リリースされるのが非常に楽しみな機能です。


……tamade_store_listって何?

以下のVizに使われているデータです。

https://public.tableau.com/app/profile/tama4105/viz/SupermarketTAMADELocationMap/Tamade_Dashboard

Discussion