PR

PHPでタグ機能を実装するときのパターン集

MySQL

あー、もとやんです。最近マジで眠いです。
タグ機能って、web2.0というワードが出現してからこっち、いろんなサイトに実装される「よくある機能」の一つでしょう。まぁ集合知でタギングしていくというのは実際問題ほとんどうまく機能しないということが現在(2016年)では言われていますね。

タグ機能実装時の選択肢

タグ機能を実装するにあたっては、データベースの構造、データ構造にいくつかの選択肢があります。
この記事ではいくつかのデータ構造の選択肢を挙げ、それぞれのメリット・デメリットを比較したいと思います。想定はMySQL5.6+です。

intersection table型

名前は適当です。多分一番よくある形。
tagsテーブル

+-------+--------+------------
|name   |type    |description
+-------+--------+------------
|id     |int     |主キー(サロゲートキー,auto increment)
|tag    |vchar   |タグ(タグとして使う文字列が入る)
+-------+--------+------------

taggingsテーブル

+----------+-----+-----------------
|tag_id    |int  |target_idとの複合主キー
|target_id |int  |tag_idとの複合主キー
+----------+-----+------------------

target_idはタグを振る対象となるモデルの主キーに対する外部キーです。

このDB構造がタグ構造では一番よくあるタイプでしょう。正規化できてるし。
また、「管理者が振ったタグは一般ユーザには消せない」などのロール管理はtaggingsテーブルにroleを管理するフィールドを足せば対応できるので、そのあたりの柔軟さは有ります。

ただしタグを消したりつけたりしているうちに、tagsテーブルに参照されていないゴミが溜まったりすることが有ります。定期的にバッチでクリーニングする必要があるでしょう。
逆にアプリ側のバグでtaggingsテーブルから参照すべき先が消えてしまう・・こともあるかもしれませんが、これは外部キー制約を適切に設定しておけば大丈夫。
まぁそれを言えばtagsテーブルの孤立問題も外部キー制約と、削除時にカスケードするように設定しておけば(Mysqlの場合)問題を防げますが、あまりこの辺の機能は使われていないように思います。

なぜこういう便利なデータベースの機能が使われていないのかは、また後日。

one column with fulltext index型

同じく名前は適当。
taggingsテーブル

+-----------+-----+----
|tag_id     |int  |target_idとの複合主キー
|target_id  |int  |tag_idとの複合主キー
+-----------+-----+--

で、このtag_idをスペース区切りでFulltextインデックスを張ったフィールドにスペース区切りで突っ込むって言う。
べつにこのテーブルを使わずに直でタグを半角スペースで区切って全文インデックスつきのフィールドに足してもいいんですが、端的に言って容量の無駄。
タグテーブルを入れたほうが管理はしやすいです。実装的には、タグデータ直入れの方がシンプルに実装できるので、なるべく変な実装をしたくないという場合は良いでしょう。

適当な区切り文字でimplodeしてLIKE検索型

自分・社内用のマイクロプロジェクトでもない限り死ぬがよい。

コメント

タイトルとURLをコピーしました