はてなブクマやblog等で最近よく見かける「タグ」システムについて。


自分のサイトの商品に、
ユーザーが自分で「タグ」を指定することができるようにするには、
どういう設計をすればいいのでしょうか?

mysql/phpで構築しています。

A商品に、
ユーザXが「あ」「い」「う え」というタグをつけ、
ユーザYが「あ」「お」とタグをつけた場合、
A商品ページに
「あ」「い」「う え」「お」のタグ一覧が表示され、「あ」は2個ついてるので文字を大きくする、というようなイメージです。

タグテーブルを作って、
商品名:ユーザID:タグ などのカラム一覧で、
タグカラムにタグをカンマ区切りなどで入れていってるのかなぁ、なんて想像してます。

アドバイスや、参考になりそうなサイトを教えて頂けますとうれしいです。

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2007/06/02 07:03:15
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:elf No.1

回答回数76ベストアンサー獲得回数8

ポイント100pt

例えばこういうテーブルがあるとします.

テーブル構造

テーブル名 用途
items 商品マスター
users ユーザーマスター
item_tags 商品タグマスター
CREATE TABLE items (
    id integer NOT NULL PRIMARY KEY,
    name varchar(200) NOT NULL,
    price integer NOT NULL
);
CREATE TABLE users (
    id integer NOT NULL PRIMARY KEY,
    name varchar(200) NOT NULL,
    email varchar(200) NOT NULL,
    login_name varchar(100) NOT NULL,
    login_password varchar(40) NOT NULL
);
CREATE TABLE item_tags (
    id integer NOT NULL PRIMARY KEY,
    user_id integer NOT NULL,
    item_id integer NOT NULL,
    name varchar(200)
);
  • 実際にはプライマリキーのidは自動採番(MySQLならautoincrement,PostgreSQLならSERIAL)させるほうが好ましい
  • パフォーマンスを維持するためには適切なインデックスを付加する必要があります

レコードの追加

商品の追加は下記のようにやります.

INSERT INTO items (id, name, price) VALUES( 1, '商品1', 100);
INSERT INTO items (id, name, price) VALUES( 2, '商品2', 200);

ユーザーの追加は下記のようにやります.

INSERT INTO users (id, name, email, login_name, login_password) VALUES( 1, 'ユーザー1', 'user1', 'user1@example.com', '暗号化,ハッシュ化したパスワード');
INSERT INTO users (id, name, email, login_name, login_password) VALUES( 2, 'ユーザー2', 'user2', 'user2@example.com', '暗号化,ハッシュ化したパスワード');

この上で,「user1」さんが商品番号1にタグ「書籍」「参考書」を付加するには下記のようにします.

INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 1, 1, 1, '書籍');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 2, 1, 1, '参考書');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 3, 1, 2, 'MUSIC');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 4, 1, 2, 'CD');

この上で,「user2」さんが商品番号1にタグ「本」「後で読む」を付加するには下記のようにします.

INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 5, 2, 1, '本');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 6, 2, 1, '後で読む');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 7, 2, 1, '参考書');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 8, 2, 2, 'CD');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 9, 2, 2, '音楽');

こうすることにより,商品に付加されたタグの数などをSELECG時にSQLだけで算出することができるようになります.

テストSQL

ユーザー1が商品1に付加している商品にタグ

SELECT * FROM item_tags WHERE user_id = 1 AND item_id = 1;

商品にタグを貼っているユーザー数

SELECT COUNT(*) FROM (SELECT user_id FROM item_tags WHERE item_id = 1 GROUP BY user_id) AS rows;

商品に貼られている全タグ

SELECT * FROM item_tags WHERE item_id = 1 GROUP BY name;

ユーザー1が商品に付加している全タグ

SELECT name FROM item_tags WHERE user_id = 1 GROUP BY name;

軽くテストしただけなのでSQLミスなどあるかもしれません.

id:onigirin

どうもありがとうございます。

それぞれ1レコードごとにタグ管理すると便利なのですね。

とてもわかりやすかくて助かりました。

データベースやテーブルの設計も悩んでいたので、

こちらの部分でもとても参考になりました。

ありがとうございます!

2007/05/28 16:05:42

その他の回答2件)

id:elf No.1

回答回数76ベストアンサー獲得回数8ここでベストアンサー

ポイント100pt

例えばこういうテーブルがあるとします.

テーブル構造

テーブル名 用途
items 商品マスター
users ユーザーマスター
item_tags 商品タグマスター
CREATE TABLE items (
    id integer NOT NULL PRIMARY KEY,
    name varchar(200) NOT NULL,
    price integer NOT NULL
);
CREATE TABLE users (
    id integer NOT NULL PRIMARY KEY,
    name varchar(200) NOT NULL,
    email varchar(200) NOT NULL,
    login_name varchar(100) NOT NULL,
    login_password varchar(40) NOT NULL
);
CREATE TABLE item_tags (
    id integer NOT NULL PRIMARY KEY,
    user_id integer NOT NULL,
    item_id integer NOT NULL,
    name varchar(200)
);
  • 実際にはプライマリキーのidは自動採番(MySQLならautoincrement,PostgreSQLならSERIAL)させるほうが好ましい
  • パフォーマンスを維持するためには適切なインデックスを付加する必要があります

レコードの追加

商品の追加は下記のようにやります.

INSERT INTO items (id, name, price) VALUES( 1, '商品1', 100);
INSERT INTO items (id, name, price) VALUES( 2, '商品2', 200);

ユーザーの追加は下記のようにやります.

INSERT INTO users (id, name, email, login_name, login_password) VALUES( 1, 'ユーザー1', 'user1', 'user1@example.com', '暗号化,ハッシュ化したパスワード');
INSERT INTO users (id, name, email, login_name, login_password) VALUES( 2, 'ユーザー2', 'user2', 'user2@example.com', '暗号化,ハッシュ化したパスワード');

この上で,「user1」さんが商品番号1にタグ「書籍」「参考書」を付加するには下記のようにします.

INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 1, 1, 1, '書籍');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 2, 1, 1, '参考書');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 3, 1, 2, 'MUSIC');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 4, 1, 2, 'CD');

この上で,「user2」さんが商品番号1にタグ「本」「後で読む」を付加するには下記のようにします.

INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 5, 2, 1, '本');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 6, 2, 1, '後で読む');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 7, 2, 1, '参考書');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 8, 2, 2, 'CD');
INSERT INTO item_tags (id, user_id, item_id, name) VALUES( 9, 2, 2, '音楽');

こうすることにより,商品に付加されたタグの数などをSELECG時にSQLだけで算出することができるようになります.

テストSQL

ユーザー1が商品1に付加している商品にタグ

SELECT * FROM item_tags WHERE user_id = 1 AND item_id = 1;

商品にタグを貼っているユーザー数

SELECT COUNT(*) FROM (SELECT user_id FROM item_tags WHERE item_id = 1 GROUP BY user_id) AS rows;

商品に貼られている全タグ

SELECT * FROM item_tags WHERE item_id = 1 GROUP BY name;

ユーザー1が商品に付加している全タグ

SELECT name FROM item_tags WHERE user_id = 1 GROUP BY name;

軽くテストしただけなのでSQLミスなどあるかもしれません.

id:onigirin

どうもありがとうございます。

それぞれ1レコードごとにタグ管理すると便利なのですね。

とてもわかりやすかくて助かりました。

データベースやテーブルの設計も悩んでいたので、

こちらの部分でもとても参考になりました。

ありがとうございます!

2007/05/28 16:05:42
id:orz66 No.2

回答回数106ベストアンサー獲得回数11

ポイント27pt

ご存知かもしれませんが

pearのタグクラウド生成用のライブラリ

http://phpspot.org/blog/archives/2006/06/phphtml_tagclou.html

id:onigirin

どうもありがとうございます。

pearにこんなものまで・・・。

コーディングの参考になりそうです。

ありがとうございます。

2007/05/28 17:13:53
id:elf No.3

回答回数76ベストアンサー獲得回数8

ポイント26pt

この質問普段ぼーっと考えていたことなのでちょうどよかったというだけで(苦笑

ちなみにphpspotのものは今となっては情報が古いですね.

件のパッケージは既に正式リリースされています.

http://pear.php.net/package/HTML_TagCloud

pearコマンドが正常に動作する(かつバージョン1.4系以上)なら

$ pear install --alldeps HTML_TagCloud     (LinuxなどUNIX系の場合)
$ pear.bat install --alldeps HTML_TagCloud (Windowsの場合)

でインストールできるかもしれません

(場合によってはrootやAdministratorなどの管理者権限が必要です)

マニュアルも公式な日本語マニュアルがあるので参考になさってください.

http://pear.php.net/manual/ja/package.html.html-tagcloud.php

id:onigirin

どうもありがとうございます。

pear使うとホントに楽ですねぇ・・・。

でもpear使うと自由度が低くなりそうで混乱しそうなので、

教えて頂いたコードを基本として、

pearのコードを参考にしながら作ってみようかな、と思っています。

こんなに読みやすくコードを表示して頂けると、

参考にしながら自分で打ちたくなってきますね(笑)

2007/05/29 14:41:16
  • id:karasimiso
    elfさんの優しさに泣いた。
    まさか人力検索でデータベースのプロトタイプを設計して提案してくるとは。

    もしこれが仕事としてやっていたなら
    報酬が10000ポイントでも足りないんじゃないか?
    とか思いながら拝見させていただきました。
  • id:onigirin
    初め回答を開いたとき、ものすごく驚きました。
    なにより設計がすごく参考になって、本当助かりました。

    この回答がまた検索エンジンに残り
    多くの人が参考にしていくと思うと、
    はてなは本当にすごい場を提供しているなぁ、と
    しみじみ思いますねぇ。

    良いサイトを構築し、
    頂いた知識を活かしていきたいですね。
  • id:elf
    しまった2発めはコメントのつもりだったのに回答にしてしまった(苦笑
  • id:elf
    補足ですがこちらも参考になると思います

    http://www.mono-space.net/blog/pgsql/e070528_tag_table.htm
  • id:onigirin
    どうもありがとうございます。
    このサイトもとても参考になりますね。
    設計部分が見えると理解しやすくて助かりますねぇ。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません