タグ付けのための合意された理想的なスキーマはありますか
質問
写真のウェブサイトを所有しており、元のカテゴリバケットが失敗し始めているため、タグをサポートしたいです(一部の写真は家族や休暇、または学校や友人です)。合意されたタグ付けDBスキーマはありますか?
アルバムの一部として写真を保持することを引き続きサポートしたい。
今、いくつかのテーブルがあります:
写真
- PhotoID
- PhotoAlbumID
- キャプション
- 日付
フォトアルバム
- AlbumID
- AlbumName
- AlbumDate
解決
効果的なさまざまなスキーマがあり、それぞれにタグ付きアイテムの数が増えると必要になる一般的なクエリに対するパフォーマンスの影響があります。
- http://howto.philippkeller.com/2005/ 04/24 / Tags-Database-schemas /
- http://howto.philippkeller.com/2005/ 06/19 / Tagsystems-performance-tests /
個人的には、非正規化(タグ名の重複なし)でタグテーブルとアイテムにタグを関連付けるリンクテーブルがあり、リンクテーブルに追加情報(アイテムがタグ付けされたときなど)を保存できるため、必要な場合。
タグテーブルに使用回数を保存するか、アイテムテーブル自体で使用されたタグ名を保存することで必要な追加のデータメンテナンスを犠牲にして、簡単に選択したい場合は、非正規化データを追加することもできます各アイテムのリンクテーブルとタグテーブルにヒットしないようにします。これは、すべてのタグを含む複数のアイテムを表示したり、タグのバージョン管理を簡単にしたりする場合に便利です。
他のヒント
これは、非常に多くのユーザーがいない小さなシステムで実行しましたが、以前に「承認済み」があったかどうか疑問に思っていました。タグを管理する方法。 insinによって投稿されたリンクやタグ付けに関する他の多くのブログ記事を読んだ後、データセットが大きくなりすぎた場合に完全に正規化して特定のものをキャッシュすることは受け入れられている方法のようです。
多対多の関係であるため(各タグは任意の数の写真に属することができます-各写真には多くのタグを含めることができます)、リレーショナルデータベース理論では、写真テーブル、タグテーブル、および相互参照テーブルを作成してリンクしますそれら。
photos
photoid
caption
filename
date
tags
tagid
tagname
phototags
photoid
tagid
これには、非常に大きなデータセットから選択するスケーリングの問題がありますが、すべての非正規化スキーマも同様です(たとえば、テキストフィールドによるソートとフィルタリングは、おそらく整数を使用するよりも常に遅くなります)。おいしいほど大きくなった場合、またはStackOverflowでさえ大きくなった場合は、おそらくタグセットのキャッシュを行う必要があります。
他に直面しなければならない問題は、タグの正規化の問題です。これはデータベースの正規化とは関係ありません-(たとえば)" StackOverflow"、" stackoverflow"および「スタックオーバーフロー」タグは同じです。多くの場所で空白が許可されないか、空白が自動的に削除されます。句読点についても同じことがわかります-「StackOverflow」を作成します" Stack-Overflow"と同じです。自動下降はかなり標準的です。特別な場合の正規化(「c#」の作成など)も表示されます。 " csharp"と同じ。
Happy tagging!
このようなことが思い浮かびます:これら2つのテーブルを追加します
タグ
- TagID
- TagName
- TagDescription
PhotoTags
- PhotoID
- TagID
これをアルバムに拡張して、フォトアルバムとタグの間に交差テーブルを作成することもできます。
確立されたオープンソースソフトウェアがそれをどのように行うかを調べることをお勧めします。たとえば、 Gallery は、そのメタデータをあなたと同じようにデータベースに保存し、非常に豊富です。
「標準」が見つかるとは思わないただし、スキーマ。私が考えることができる最も近いものはEXIFメタデータ形式であり、それは画像ファイル自体に(カメラなどによって)埋め込まれます。
数百万のレコードで実際のパフォーマンスが必要な場合は、sphinxsearchのようなフルテキストインデックス/検索デーモンを使用して、タグを1つのフィールドに格納し、カンマ区切りでレコードを取得できます。追加する必要があるのは、すべてのタグをカウント値とともにリストするテーブルで、それらがアイテムに添付される頻度を知るためです。
通常の方法ではなく、純粋なデータベースソリューションよりもやや複雑ですが、タグ関連のアイテムを検索するのは非常に高速です。
データベースエンジンの全文検索機能も使用できますが、レコードが多い場合、ほとんどのエンジンは遅くなる傾向があります。
小規模プロジェクトの場合は、自分の道を行くことができます。しかし、私はあなたにこの他のソリューションを共有したいと思います。あなたはどう思いますか?
私のアプリBugTracker.NETでは、バグが多すぎることはないと想定しています。数万人かもしれませんが、数千万人ではありません。この仮定により、タグとそれらが参照するアイテムのIDをキャッシュできます。
データベースでは、タグが入力されたときに、バグとともに、カンマ区切りのテキストフィールドに保存されます。
タグフィールドが追加または変更されると、すべてのバグIDとそのタグを選択するバックグラウンドスレッドが開始され、テキストが解析され、キーがタグで値がすべてのIDのリストであるマップが構築されますそのタグを持っています。次に、そのマップをAsp.Net Applicationオブジェクトにキャッシュします。
今説明したコードは次のとおりです。
コードを最適化して、すべてのバグを処理するのではなく、キャッシュされたマップをインクリメンタルに変更するだけで、最適化されていない場合でも正常に動作するようにできます。
誰かがタグを使用して検索を行う場合、マップ内の値を検索し、IDのリストを取得してから、SQLを使用して" where id in(1、2、3 ...) "句。
public static void threadproc_tags(object obj)
{
System.Web.HttpApplicationState app = (System.Web.HttpApplicationState)obj;
SortedDictionary<string,List<int>> tags = new SortedDictionary<string,List<int>>();
// update the cache
DbUtil dbutil = new DbUtil();
DataSet ds = dbutil.get_dataset("select bg_id, bg_tags from bugs where isnull(bg_tags,'') <> ''");
foreach (DataRow dr in ds.Tables[0].Rows)
{
string[] labels = btnet.Util.split_string_using_commas((string) dr[1]);
// for each tag label, build a list of bugids that have that label
for (int i = 0; i < labels.Length; i++)
{
string label = normalize_tag(labels[i]);
if (label != "")
{
if (!tags.ContainsKey(label))
{
tags[label] = new List<int>();
}
tags[label].Add((int)dr[0]);
}
}
}
app["tags"] = tags;
}
タグの処理方法に関する簡単なメモ:
タグ付けシステムは、新しいタグの作成に明示的な追加作業が必要な非常に厳密に定義されたタグ(Gmailを考える)から、できるだけ多くのタグの追加が推奨される非常にゆるいシステム(flickrを考える、または音声コンテンツにタグ付けすることができる場合)タグとして直接適用されます)。
一般に、コンテンツ自体はタグであるため、簡単にインデックス付け可能なメディア(テキスト!)はより厳格なシステムを使用する必要があります。追加のタグは分類のみに使用されます。インデックスを作成するのが難しいメディア(画像、ビデオ)には、検索時に唯一の希望があるため、多くのタグを奨励する柔軟なシステムが必要です。
これは重要です。なぜなら、必要なデータベーススキーマは、そのスペクトルのどちらの端にいるかによって多少変わる可能性があるからです。