4

タグ データベース スキーマの Toxi ソリューションについて頭を悩ませています。ユーザーがアイテムを送信できるシステムに取り組んでおり、それらのアイテムにタグを関連付けることができます。tagschemas を読んだ後、Toxi ソリューションが私のニーズに最も適していることがわかりました。ただし、これが正しい計画であるかどうかは完全にはわかりませんので、ご意見をお聞かせください。

3 つのデータベースがあります。
itemsを含みitem_id、その他 を外部キーとして
tagmap使用しitem_id、およびを含むtag_id
tagstag_idtag_text

新しいアイテムを追加する場合、タグをデータベースに追加するプロセスは次のように仮定してもよろしいですか?

  1. 送信されたタグを配列に並べ替える
  2. 配列内のすべてのタグに対して:
    1. tag_text が現在のタグと一致するタグから tag_id を取得する
    2. それが0行を返す場合:
      1. タグテーブルにタグを追加
      2. tag_id を取得する
    3. item_id と tag_id を tagmap に追加
  3. 終了 (ユーザーに a-ok などを与える)

これは、すべてのアイテムのすべてのタグのタグマップにエントリが作成されることを意味します。それは正しいように思えますが、膨大な量のエントリで終わるよりも、それを行うためのより良い方法があると思わずにはいられません...

タグの編集に関しては、次のプロセスを考えましたが、まだ見つかっていないより良い方法があると思います。

  1. item_id を使用してタグを取得し、編集可能なフィールドに挿入します
  2. ユーザーが変更を行います。提出時:
  3. item_id が編集中のものと一致するタグマップから行を削除します
  4. 上記と同じプロセス

私はそこにあるポイント3についてちょっと不安です。タグが削除されたかどうかを確認して、タグを削除して再度追加するのではなく、タグを選択的に削除する方法はありますか? 念のために言っておきますが、tagmap 行を削除しても、関連するアイテムは一緒に削除されません。これは、外部キーとして機能するのではなく、外部キーを指しているからです。

また、タグが使用された回数を追跡したい場合もありますが、表示する必要があるたびにそれらをカウントするクエリを実行したくありません。cron ジョブで、tagmap のすべての tag_id のインスタンス数を 1 時間ごとまたは 2 時間ごとにカウントしてから、tags テーブルの tag_use 値を更新することを考えています。それは正しい方法ですか、それとももっと良い方法はありますか?

振り返ってみると、かなりの量のテキストです。情報が不足しているよりも詳細すぎて、質問が少なすぎるよりも、質問が多すぎて新しいことをたくさん学んでいます。今日はこれを調べるのに多くの時間を費やした可能性が高く、明日はすべてがより理にかなっているでしょう.

前もって感謝します!

4

1 に答える 1

15

まず第一に、「トキシ」は標準的な用語ではありません。常に用語を定義してください!または、少なくとも関連するリンクを提供します。

そして今、質問自体に...

3つのデータベースがあります。

いいえ、3つのテーブルがあります。

新しいアイテムを追加するとき...

SQLのセットベースの性質を使用してこれらのステップの多くを「マージ」できることを除いて、あなたはほぼ正しい方向に進んでいます。たとえば、アイテム1に「tag1」、「tag2」、「tag3」のタグを付けると、次のようになります。

INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');

IGNORE、アイテムがこれらのタグの一部にすでに接続されている場合でも、これを成功させることができます。

これは、必要なすべてのタグがすでににあることを前提としていtagsます。自動インクリメントであると仮定するとtag.tag_id、次のようにして、次のことを確認できます。

INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');

これは、すべてのアイテムのすべてのタグのタグマップにエントリが作成されることを意味します。それは正しいようですが、私はそれを行うためのより良い方法があると思いますが、そこに大量のエントリがあります...

魔法はありません。「アイテムが特定のタグに接続されている」が記録したい知識の一部である場合、データベースに何らかの物理的表現が必要になります

タグの編集は...

アイテムにタグを付け直すことを意味します(タグ自体を変更するのではありません)?

リストにないすべてのタグを削除するには、次のようにします。

DELETE FROM tagmap
WHERE
    item_id = 1
    AND tag_id NOT IN (
        SELECT tag_id FROM tags
        WHERE tag_text IN ('tag1', 'tag3')
    );

これにより、「tag1」と「tag3」を除くすべてのタグからアイテムが切断されます。上記のINSERTを実行し、このDELETEを次々に実行して、タグの追加と削除の両方を「カバー」します。

SQLフィドルでこれらすべてを試すことができます。

念のために言っておきますが、タグマップ行を削除する場合、関連アイテムは外部キーとして機能するのではなく外部キーを指しているため、一緒に削除されることはありません。

正しい。FKの子エンドポイントは、参照アクション(ON DELETE CASCADEなど)をトリガーせず、親のみがトリガーします。

tagsところで、 (の横に)追加のフィールドが必要なため、このスキーマを使用していますよtag_textね?その場合、すべての接続が失われたという理由だけでこの追加データを失わないことが望ましい動作です。

ただし、が必要な場合はtag_text、すべての接続を削除することはタグ自体を削除することと同じである、より単純なスキーマを使用します。

ここに画像の説明を入力してください

これにより、SQLが単純化されるだけでなく、より優れたクラスタリングも提供されます。

一見、「toxi」はスペースを節約しているように見えるかもしれませんが、追加のテーブルとインデックスが必要になるため(タグは短くなる傾向があるため)、実際にはそうではない場合があります。

また、タグの回数を追跡したい場合があります...cronジョブ...

このようなことをする前に測定してください。上記の私のSQLFiddleは、tagmapPK内のフィールドの非常に慎重な順序を使用しているため、データはこの種のカウントに非常に適した方法でクラスター化されます(InnoDBテーブルはクラスター化されていることに注意してください)。これが問題になる前に、本当に大量のアイテムを持っている必要があります(または非常に高いパフォーマンスが必要です)。

いずれにせよ、現実的な量のデータで測定してください!

于 2012-05-09T19:01:32.437 に答える