anilogia/animedb

「識別名」でない識別子を作品に振る

Closed this issue · 0 comments

背景

今のところ,Anime DB で扱っている情報は「タイトル」「よみがな」「放送開始日」といったアニメそのものの基本情報と,一部の各話情報(エピソード)のみである.
今後,スタッフやキャラクターといった情報を追加する場合,作品横断的な扱いが要求される(1対多ではなく多対多).その際,現在の「識別名」には変更可能性が存在するため,それを作品との関連付けに用いることは不適当である.
そのため,他のあらゆるデータベースと同様に,それ自体に意味がない識別子(e.g. 0000001abcdefg)を用いる必要がある.
喫緊の課題でなかったため先送りしていたが,そろそろ解決した方が良い.

主問題

  1. 多対多のような関連付けを行い易い識別子が作品に付けられていない
    • 「識別名」が全作品に対して一意であるため,今でも「識別名」を用いれば関連付けは可能だが,「識別名」は「タイトル」と「添え名」から構成されており,変更可能性が存在する

副問題

  1. 識別子として何を用いるか(識別子をどのように生成するか)
  2. 主問題1の識別子を導入した後,既存の「識別名」の扱いをどうするか

解決方法案

1. 識別子として何を用いるか(識別子をどのように生成するか)

前提として,現在・将来に渡って識別子に「一意である」以上の意味を持たせないようにする.つまり,ランダム文字列が望ましい.
その上で,作品に振る識別子の要件を,優先度が高いと思われる順に以下に挙げる.

  1. 識別子がすぐには枯渇しない
  2. 生成し易い
  3. 編集し易い(e.g. 一回のダブルクリックで識別子全体が選択される)
  4. 見易い
  5. 短い

以上の要件を良く満たす識別子の生成方法を以下に示す.

  1. UUID v4を生成する
  2. 生成した UUID を Base57 でエンコードする
  3. 生成した Base57 文字列の最初の 11 文字を識別子として使う(e.g. vytxeTZskVK

Base57 はデータを 57 種の文字でエンコードするため,57^11 = 20,635,899,893,042,801,193 サイズの空間を持つ.しかし,ランダムに生成する場合,Birthday problem と同様に,素朴な直感に反して生成数が非常に小さい段階で衝突確率が 50% 以上になる.
11 文字の場合,2つ以上の識別子が被る確率が 50% 以上になる生成数は,およそ 5,348,591,559 個である.

animedb コマンド以外にも,GitHub Pages などで識別子を生成できるようにする.

2. 主問題1の識別子を導入した後,既存の「識別名」の扱いをどうするか

「識別名」は元々,表示の際に同名の作品が現れないようにするために導入された.
今のところ,「識別名」自体を id として Anime DB に書いているが,代わりに識別子を id として記入することになる.
「識別名」は「タイトル」と「添え名」から容易に作れるので,それ単体で保存する必要はない.「識別名」という概念(つまり一意性の担保)だけ残しておく.