森高千里データベースの再構築(10) : hkob の雑記録 (210)

はじめに

hkob の雑記録の第210回目は、Concerts & Devices の曲目リストとなる SetList を追加します。

ER図

SetList は Concerts, Devices に接続します。逆に Performances から SetLists に接続されます。Year, Map はさまざまなものに接続されるので、プロパティだけの表示とします。逆にリレーションの線を繋いでいるものはプロパティ表記を省略します。

ER図

SetLists のエクスポート

SetLists は以下のプロパティをエクスポートすることにします。SetLists は Concerts および Devices の二つのデータベースのどちらかに接続します。本当は先に SetLists を作っておき、後から昨日作成した Performances に繋げるべきでした。話間違えて先に Performances を作ってしまったので、SetLists 側から接続することにします。昨日と同様に Name は後から差し替えをするので、DeviceKindsCopy を Name として登録しておきます。

SetLists のプロパティの選択

作成した CSV ビューはこんな感じです。今回も Name は後から修正します。

エクスポートする CSV ビュー

前回と同様に CSV に書き出し後、リレーションの URL 削除をしてしまいます。

sed 's/ (https:\/\/www.notion.so[^)]*)//g' Set\ lists\ babb7c61c5364530bb06525df5a5ad1d.csv | sed 's/\([0-9][0-9]*\)\/\([0-9][0-9]*\)\/\([0-9][0-9]*\)/\1-\2-\3/g' | sed 's/ → /\//g' > SetLists.csv

変換結果は以下のようになります。昨日と同様にここからリレーションを設定します。

Type,Device,DeviceKinds,Name,Concert,Performances
アルバム(NEW SEASON),NEW SEASON,アルバム,アルバム,,
シングル(NEW SEASON),NEW SEASON,EPシングル,EPシングル,,
Set list A,,,,渋谷ライブイン ファーストライブ,01
Set list A,,,,"「OVERHEAT. NIGHT」, 「GET SMILE」",02

SetLists の作成 & インポート

森高千里DBの下に作成したいので、また Cmd-Opt-9 で新規ページを作成します。この新規ページを開き、インポートを実施しました。

CSV列の設定

インポートを実行しました。

インポート完了

リレーションの作成

名前を修正するのを忘れたので、Concert, Devices, Performances の名前を DeviceStr, ConcertStr, PerformancesStr に変更しておきます。その後、Concert と Device リレーションを追加します。Concert は1対多の関係となります。このため、1ページ制限を付加しています。Devices は同じセットリストが複数のものに繋がることがあるので、こちらは多対多となります(後から気づいて修正しました)。また双方向リレーションも追加します。

Concert relation

Devices relation

一方で、Performances データベースに SetLists へのリレーションを追加します。Performances 側で 1 ページの制限を付けたいので、こちら側から設定します。

SetList relation

ここまでやって、Device type をコピーし忘れたので、インポートからやり直しました。スクリーンショットを撮り直すのは大変なので、このままにします。

Notion API で Concert, Devices, Performances データを準備

今回は流石に複数プロパティから id を取得したりする必要があり、かなり面倒な処理となるので、スクリプトを記載しました。Device は Name と Device type で一意のページを取得します。Concert は Name だけで一意のページを取得できますが、Performances は数値しかありません。そのため、Concert の Name と Num でハッシュを作り、一意にページを特定します。

#! /usr/bin/env ruby

require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["NOTION_API_KEY"] }

devices_db = Database.find "236d8e4e98ab80e0b548f6e419a81edb"
devices_id_hash = devices_db.query_database.each_with_object({}) do |device, hash|
  name = device.properties["Name"].full_text
  device_type = device.properties["Device type"].select["name"]
  hash[[name, device_type]] = device.id
end

concerts_db = Database.find "239d8e4e98ab806186e0e6e9a36b14ff"
concerts_id_hash = concerts_db.query_database.each_with_object({}) do |concert, hash|
  name = concert.properties["Name"].full_text
  hash[name] = concert.id
end

performances_db = Database.find "23cd8e4e98ab8049a856c05ad8eac93a"
performances_id_hash = performances_db.query_database.each_with_object({}) do |performance, hash|
  name = performance.properties["Name"].full_text
  num, concert_name, = name.split " "
  hash[[num.to_i, concert_name]] = performance.id
end

set_lists_db = Database.find "23dd8e4e98ab80739da0d79d60a9f905"
cp = set_lists_db.properties["Concert"]
dp = set_lists_db.properties["Devices"]
query = cp.filter_is_empty.and(dp.filter_is_empty)
set_lists_db.query_database(query).each do |sl|
  p sl.id
  sp = sl.properties
  if !(devices_str = sp["DeviceStr"].full_text).empty?
    device_type = sp["Device type"].full_text
    devices_str.split(", ").each do |device_str|
      if (device = devices_id_hash[[device_str, device_type]])
        sp["Devices"].relation = [device]
        p device_str, device_type
      end
    end
  elsif !(concert_str = sp["ConcertStr"].full_text).empty?
    if (concert = concerts_id_hash[concert_str])
      sp["Concert"].relation = [concert]
      p concert_str

      if (performances_str = sp["PerformancesStr"].full_text)
        nums = performances_str.split(", ").map(&:to_i)
        ids = nums.map { |num| performances_id_hash[[num, concert_str]] }
        sp["Performances"].relation = ids
        p concert_str, nums
      end
    end
  end
  sl.save
end

実行結果は以下のようになりました。

ruby relation_for_set_list.rb
"23dd8e4e98ab81fdb8c9eb4032cb01b8"
"23dd8e4e98ab812fb8e0e5d5e752be5f"
"「サバサバ」ツアー"
"「サバサバ」ツアー"
[2, 3, 4, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27]
"23dd8e4e98ab817bb138d95ad7b1d5a5"
"23dd8e4e98ab813cb605c44c45235813"
"Live GiRLPOP ACT 22"
"Live GiRLPOP ACT 22"
[1]
"23dd8e4e98ab817bb3d8fbad98769923"
"Act Against AIDS '97 ついに「THE VARIETY 5」"
"Act Against AIDS '97 ついに「THE VARIETY 5」"
[1]
"23dd8e4e98ab81d88fd3dc227f8ce91f"
"23dd8e4e98ab81968ba7c7dcdb44b42e"
"「PEACHBERRY SHOW」ツアー"
"「PEACHBERRY SHOW」ツアー"
[14]

結果として以下のようにリレーションが設定できました。

設定されたリレーション

必要なくなったプロパティを削除し、Type を綺麗に整理しました。

不必要なプロパティを削除後

Name を自動設定するオートメーション

昨日の Performance と同様に Name を Type と Device または Concert から自動設定するようにしてみます。

Name を自動設定するオートメーション

ここで設定した値は以下のように設定しました。

設定した値

オートメーションの確認

試しに最初の一つだけタイトルの文字列を消してみたところ、想定通りのタイトルが設定されました。

タイトル文字列のテスト

あとは全てのタイトルを削除したところ、一気にタイトルが自動設定されました。

タイトル全てを変更

おわりに

Set Lists については単一プロパティでは一意にリレーションを設定できませんでした。複数プロパティを使ってページを特定することで、207件の SetLists を手動で設定しなくてよくなり助かりました。

hkob.notion.site