kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

Metabaseことはじめ④

引き続きMetabaseやっていきます。

今回は以下の記事で紹介されているお題の残りをやりたいと思います・

データソースはこちら。

qiita.com

目次

お題2: 日本に住んでいるお客さんの名前

国名にたどり着くために、address→city→countryと複数のテーブルの結合を繰り返す感じですね。

結果

かんたんですね。

お題3: 2005年5月26日にレンタルされた映画のカテゴリ別のレンタル回数ランキング

ちょっと難しそうですね。元記事と同じようにやっていきましょう。

Rentalテーブルでフィルタを設定して、Rental Dateが2005/05/26のものを引っ張ってきます。キャプチャだけさらっと。

こんな感じで抽出できます。

次に、inventory→film_category→ categoryと結合していってカテゴリを抽出します。

こういう結果になります。余計な出力は一旦取りました。

ではこれを集計します。「要約」からカテゴリ名(Category → Name)をキーにグループ化して件数をカウントします。

ビジュアライズするとこうなります。棒グラフが自動的に選択されてますね。

でレコード数を降順でソートしましょう。

はい、きれいに並びました。

ビジュアルを変えるとまた印象が変わりますね。

まとめ

とてもかんたんですね。商用のものに比べると機能的に物足りないというところもおそらくあるかと思うのですが、なにせ操作がわかりやすいです。これならエンジニアでなくても扱えそうですし、BIはじめてという方にもいいのではないでしょうか。

いろいろ解析したいデータがあるのでちょくちょく使ってみようと思います。

AWS CDKことはじめ

新年らしくことはじめで。

AWSへのリソース作成はTerraformを使うことが多いのですが、ちょっと他のチョイスも見ておきたい、ということでAWS CDKをかじってみます。

単に以下を写経する感じなので、あくまでも個人のメモです。

目次

前提

$ node -v
v18.12.0

$ aws --version
aws-cli/2.9.13 Python/3.11.1 Darwin/21.6.0 source/x86_64 prompt/off

AWS CDKのインストール

$ npm install -g aws-cdk

$ cdk --version
2.59.0 (build b24095d)

CDKブートストラップの設定

AWS CDKを使ったデプロイに必要なリソースを作成する(あくまでもCDKを使えるようにするためのリソースであって、自分がCDKで作成するリソースとは別)。アカウント+リージョンで1回だけ実行する必要がある。アカウントIDとリージョンを指定して以下のように実行する。

$ cdk bootstrap aws://123456789012/ap-northeast-1

CDKプロジェクトの作成

今回はTypeScriptでやってみる

$ mkdir hello-cdk & cd hello-cdk

$ cdk init app --language typescript
Applying project template app for typescript
# Welcome to your CDK TypeScript project

This is a blank project for CDK development with TypeScript.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build`   compile typescript to js
* `npm run watch`   watch for changes and compile
* `npm run test`    perform the jest unit tests
* `cdk deploy`      deploy this stack to your default AWS account/region
* `cdk diff`        compare deployed stack with current state
* `cdk synth`       emits the synthesized CloudFormation template

Initializing a new git repository...
Executing npm install...
✅ All done!

アカウント・リージョンの設定

us-east1以外の場合、CDKプロジェクトからbootstrapで作成したCloudFormationスタックを使うように指定する必要がある様子(指定しなければus-east1がデフォルトになった)。binの下にあるTSファイルに記載する。今回の場合だとbin/hello-cdk.ts。

import { HelloCdkStack } from '../lib/hello-cdk-stack';

const app = new cdk.App();
new HelloCdkStack(app, 'HelloCdkStack', {
  env: { account: '123456789012', region: 'ap-northeast-1' },
});

リソースを作成する ①S3の場合

作成したいリソースは、libディレクトリ以下に記載する。今回の場合だとlib/hello-cdk-stack.tsになる。デフォルトだとこんな感じ。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'HelloCdkQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}

モジュールから作成したいリソースのクラスをインポートする。

import { aws_s3 as s3 } from 'aws-cdk-lib';

S3バケットを作成する。The code that defines your stack goes hereの箇所に書いていく

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });

設定するパラメータなどはAPIリファレンスを見るとよい。

こんな感じになる。コメントアウト部分は全部はずしてある。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_s3 as s3 } from 'aws-cdk-lib';

export class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

生成されるCloudFormationテンプレート

AWS CDKでは、書いたコードが直接実行されてリソースが作成されるのではなく、ここからCloudFormationテンプレートが生成されてそれを元にリソースが作成される。 どのようなCloudFormationテンプレートが生成されるかはsynthで確認できる。

$ cdk synth
Resources:
  MyFirstBucketB8884501:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: HelloCdkStack/MyFirstBucket/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/zPSM7XUM1BMLC/WTU7J1s3JTNKrDi5JTM7WAQrFFxvrVTuVJmenlug4p+VBWLUgZlBqcX5pUXJqrU5efkqqXlaxfpmhhZ6hEdCorOLMTN2i0rySzNxUvSAIDQC9CLZrZgAAAA==
    Metadata:
      aws:cdk:path: HelloCdkStack/CDKMetadata/Default
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Rules:
  CheckBootstrapVersion:
    Assertions:
      - Assert:
          Fn::Not:
            - Fn::Contains:
                - - "1"
                  - "2"
                  - "3"
                  - "4"
                  - "5"
                - Ref: BootstrapVersion
        AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.

最後のAssertDescriptionがこうエラーっぽく見えるけど気にしなくて良い。

デプロイ

ではデプロイする。

$ cdk deploy

✨  Synthesis time: 7.4s

HelloCdkStack: building assets...

(snip)

HelloCdkStack: creating CloudFormation changeset...

 ✅  HelloCdkStack

✨  Deployment time: 39.02s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/HelloCdkStack/01b19fe0-9043-11ed-8442-0a5df6f0b7c7

✨  Total time: 46.41s

作成されているかどうか確認

$ cdk ls
HelloCdkStack

HelloCdkStackというCloudFormationのスタックが作成されている。ここでリソースは管理される。

実際のリソースを確認してみる。

$ aws s3 ls | grep -i MyFirstBucket
2023-01-10 02:28:31 hellocdkstack-myfirstbucketb8884501-8hiaovkccah6

$ aws s3api get-bucket-versioning --bucket hellocdkstack-myfirstbucketb8884501-8hiaovkccah6
{
    "Status": "Enabled"
}

ちゃんと作成されている。

リソースの変更

次にリソースの変更を試してみる。手元のコードとスタックとの差分をチェックする。

$ cdk diff
Stack HelloCdkStack
There were no differences

当然変更はない。ではS3バケットのバージョニングを無効にする。

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: false
    });

再度diffしてみる。

$ cdk diff
Stack HelloCdkStack
Resources
[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501 
 └─ [-] VersioningConfiguration
     └─ {"Status":"Enabled"}

デプロイして変更する。

$ cdk deploy
(snip)
HelloCdkStack: creating CloudFormation changeset...
[··························································] (0/3)

2:55:32 | UPDATE_IN_PROGRESS   | AWS::CloudFormation::Stack | HelloCdkStack
2:55:37 | UPDATE_IN_PROGRESS   | AWS::S3::Bucket    | MyFirstBucket
(snip)
 ✅  HelloCdkStack
(snip)
✨  Total time: 45.97s

では確認してみる。

$ aws s3api get-bucket-versioning --bucket hellocdkstack-myfirstbucketb8884501-8hiaovkccah6
{
    "Status": "Suspended"
}

バージョニングが停止された。

リソースの削除

作成したリソースを削除する。

$ cdk destroy
Are you sure you want to delete: HelloCdkStack (y/n)? y
HelloCdkStack: destroying... [1/1]

 ✅  HelloCdkStack: destroyed

これでスタックが削除されて、そこで管理されるリソースも削除される。ただしS3バケットの場合はデフォルトで削除されないので手動で削除する。(CDKの定義で自動で削除させることもできるが手動のほうがいいと思う。)

おまけ:VPCの場合

さっきのS3バケットに加えて、2AZでパブリック/プライベートのVPCを作ってみる場合はこんな感じ。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_s3 as s3 } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    const s3bucket = new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
    const vpc = new ec2.Vpc(this, 'MyFirstVpc', {
      ipAddresses: ec2.IpAddresses.cidr('10.1.0.0/16'),
      maxAzs: 2,
      subnetConfiguration: [
        {
          subnetType: ec2.SubnetType.PUBLIC,
          name: 'Public',
          cidrMask: 24,
        },
        {
          cidrMask: 24,
          name: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        }
      ]
    });
  }
  get availabilityZones(): string[] {
    return ['ap-northeast-1c', 'ap-northeast-1d'];
  }
}

ちょっとAZの指定とかやや独特感。別の書き方もできるみたいだけど。この辺はAPIリファレンス参照。

まとめ

Terraformのような宣言型のほうが学習コストも低いしかんたんではあるのだけど、ちょっとしたロジックを書こうと思うとTerraform独自の関数で記載しないといけない。TypeScriptなど言語を使って書ければそのあたりは楽になるかもしれない。

ただ、ちょっと学習コストは高めな印象。

  • ググって見た感じ、AWS CDK v1の記事が多くて、v2の場合と違うところもあってちょっと混乱した。公式ドキュメント見て迷うより、workshopやるのが一番速い。
  • パラメータをいちいち記載しなくても作れたりするのはいいんだけど、ちょいちょいエラーが出た。例えばNAT Gatewayが作れないAZもあったりとか。ちゃんと明示的に記載するほうが良い。
  • CloudFormationほとんどさわったことない人なので、エラーが出たときとかにちょいちょいタイムアウトするのはそういうものなのかなぁと。なんかこう

APIリファレンスをしっかり読むのは大事。TerraformのAWS Providerもそれは同じなんだけど、TerraformはAWSリソースの設定をやってるという感じなのに対して、CDKのほうはなんというか「CDKを触ってる」って感じ。うまく言えないんだけど、初動のところでTerraformよりも「わかった」感がなんか少ないかな。使い込んでいけば変わるのかもしれないけど。

MetabaseでBIことはじめ③

引き続きMetabaseやっていきます。

前回は以下の記事で紹介されているお題に沿ってMetabaseでデータソースの追加と可視化を行いました。

データソースはこちら。

qiita.com

お題はまだ続くのですが、その前に少しMetabaseの機能を使って前回のダッシュボードを便利にしてみたいと思います。

目次

前回のあらすじ

前回作成したダッシュボードはこんな感じでした。

Film ActorテーブルをActorテーブル、FilmテーブルとJOINさせて、ActorテーブルのFirstNameが"Nick"という条件でフィルタしたものです。

ただ現実的に考えると

  • 俳優名を名・姓で検索できる
  • フィルタ条件は適宜変更できる

ほうが便利ですよね。

ということで、カスタムカラムとダッシュボードフィルタを試してみたいと思います。

カスタムカラム

Metabaseでは、データソースのカラムを組み合わせて独自のカスタムなカラムを追加することが出来ます。カスタムカラムでは関数なども使えるので、ELT(Extract・Load・Transform)になるわけですね。

まず、前回の質問を開きます。

こんな表示が出ます。保存しない限りはいろいろ試行錯誤できるということですね。「確認しました」をクリック。

エディターを開きます。

質問のエディター画面が開きます。

一旦フィルタは削除しちゃいましょう。

カスタム列をクリックします。

こういう画面が表示されます。フィールド計算式がExcelでいうところの数式のようなものです。

ここに以下のような数式を入力します。

concat([Actor → First Name] ," ",[Actor → Last Name] )

concatはExcelでいうCONCATENATEですね。カラムは[ ]で囲んで指定します。JOINさせている場合は上記のように[JOIN先テーブル → JOIN先テーブルのカラム名]になります。

ちなみにインクリメンタルに補完もしてくれてヘルプも表示されます。が、なんかこう微妙に入力しにくいです。日本語だからかな?私の場合はテキストエディタに書いてコピペすることが多いです。

使える関数などは公式のドキュメントを参考にしてください。

最後に名前をつけます。これがビジュアライズしたときのカラム名になります。最後に「完了」をクリック。

プレビューしてみましょう。

俳優名というカラムが追加されているのがわかりますね。

ビジュアライズするとこんな感じで、これまでの姓と名に加えて、フルネームのカラムが表示されていますね。

姓と名はもう不要なので非表示にしておいて順番を入れ替えるとこんな感じですね。

保存しておきましょう。

質問を保存する場合、上書き保存も別名での保存の両方が選べます。上書きすればダッシュボードの表示も自動で変わりますし、すでにある質問から派生させていったり、みたいなことができるわけですね。今回は上書きします。

ダッシュボードフィルタ

さきほど質問からフィルターを削除しましたが、フィルターはダッシュボードからインタラクティブにできるとよいですよね。次にダッシュボードフィルタを試してみましょう。

ダッシュボードを開きます。

「編集」(鉛筆のアイコン)をクリックします。

右上の「フィルター」をクリックします。

フィルター対象のデータの性質みたいなものを選択します。この性質によってフィルター時の条件指定の仕方やインタフェースが変わるようです。今回は「俳優名」なのでテキストですね。

次にフィルターの種類を選択します。今回の場合は、俳優名を自由に検索するような感じになるので「含む」を選択します。

こんな感じの画面が表示されます。実際のダッシュボードでの表示イメージみたいな感じですね。

ではもう少し設定を。まず、フィルタ対象のカラムを選択します。もちろん「俳優名」ですね。

フィルタの細かい設定です。この設定項目はデータの性質やフィルタの種類によって変わります。「テキスト」の場合はラベルとデフォルト値が設定できます。ラベルはGUIで表示される際の文字列です。デフォルト値を設定する必要があれば設定することが出来ます。今回はラベルだけ設定しておきました。

ちなみにリンクフィルターは、複数のフィルター条件がある場合にどちらかのフィルタ結果に応じて絞り込みを行うような場合に設定します。今回はひとつだけなので設定できません。

ダッシュボードを保存します。

試してみるとこんな感じです。

できましたね。

まとめ

今回はMetabaseの機能を少し紹介する感じになりました。次回は残りのお題をやっていきたいと思います。