39

Stack Overflowのタグ付けと検索がどのように設計されているかを知りたいのですが、それはかなりうまく機能しているようです。

次のすべてを実行したい場合、優れたデータベース/検索モデルは何ですか。

  1. さまざまなエンティティへのタグの保存(どのように正規化されていますか?つまり、Entity、Tag、およびEntity_Tagテーブル?)
    • 特定のタグが付いたアイテムの検索
    • 特定の検索結果セットに適用されるすべてのタグのタグクラウドを構築する
    • 検索結果の各アイテムのタグリストを表示するにはどうすればよいですか?

おそらく、タグを正規化された形式で格納することは理にかなっていますが、#2、#4、およびおそらく#3の目的でスペース区切りの文字列としても格納することは理にかなっています。考え?

StackOverflowは検索にLuceneを使用していると聞いています。本当?SQLの最適化について議論しているポッドキャストをいくつか聞いたことがありますが、Luceneについては何も聞いていません。彼らがLuceneを使用している場合、検索結果のどれだけがLuceneからのものであり、「ドリルダウン」タグクラウドがLuceneからのものであるかどうか疑問に思います。

4

2 に答える 2

57

うわー、私は大きな投稿を書いたばかりで、とても窒息してハングアップしました。再送信するために戻るボタンを押したとき、マークアップ エディターは空でした。ああああ。

では、また行きます…

スタック オーバーフローに関しては、 SQL Server 2005 の全文検索を使用していることが判明しました。

@Grant が推奨する OS プロジェクトについて:

  • ※DotNetKicksはタグ付けにDB、全文検索にLuceneを利用しています。全文検索とタグ検索を組み合わせる方法はないようです
  • Kiggは、検索クエリとタグ クエリの両方に Linq-to-SQL を使用しています。どちらのクエリも、Stories->StoryTags->Tags を結合します。
  • どちらのプロジェクトも、誰もが一般的に推奨しているように、タグ付けに 3 テーブル アプローチを採用しています。

また、以前に見逃していた SO に関する他の質問もいくつか見つけました。

私が言及した各項目について私が現在行っていること:

  1. DB には、Entity、Tag、Entity_Tag の 3 つのテーブルがあります。DB を使用して次のことを行います。
    • サイト全体のタグ クラウドを構築する
    • タグでブラウズ (つまり、SO の/questions/tagged/ASP.NETのような URL )
  2. 検索には Lucene + NHibernate.Search を使用します
    • タグは、Lucene によってインデックス付けされた TagString に連結されます。
      • Lucene クエリ エンジン (AND / OR / NOT クエリ) をフルに活用できます。
      • テキストの検索とタグによるフィルタリングを同時に行うことができます
      • Lucene アナライザーは、より適切なタグ検索のために単語をマージします (つまり、"test" のタグ検索では、"testing" とタグ付けされたものも検索されます)。
    • Lucene は潜在的に巨大な結果セットを返します。これを 20 個の結果にページ分割します
    • 次に、NHibernate は、DB またはエンティティ キャッシュのいずれかから、ID によって結果のエンティティをロードします。
    • したがって、検索結果が DB に 0 ヒットする可能性は十分にあります。
  3. まだこれを行っていませんが、別の DB ヒットを取得するのではなく、Lucene の TagString からタグ クラウドを構築する方法をおそらく見つけようとするでしょう。
  4. これもまだ行っていませんが、TagString を DB に保存して、さらに 2 つの結合を行わなくてもエンティティのタグ リストを表示できるようにします。

これは、エンティティのタグが変更されるたびに、次のことを行う必要があることを意味します。

  • まだ存在しない新しいタグを挿入します
  • EntityTag テーブルからの挿入/削除
  • Entity.TagString の更新
  • エンティティの Lucene インデックスを更新する

私のアプリケーションでは読み取りと書き込みの比率が非常に大きいため、これで問題ないと思います。本当に時間がかかるのは Lucene のインデックス作成だけです。Lucene はインデックスからの挿入削除しかできないため、TagString を更新するためにエンティティ全体のインデックスを再作成する必要があります。そこまではドキドキしませんが、バックグラウンドスレッドでやれば大丈夫だと思います。

時が教えてくれる...

于 2008-10-28T19:44:18.967 に答える
5

それらが最適かどうかはわかりませんが、DotNetKicks と Kigg はどちらもオープン ソースの Digg クローン実装です。彼らがどのようにタグ付けや検索を行っているかを見ることができます。

多くの熟考なしに私の最善の推測:)

  1. 複数の値を単一のフィールドにシリアル化するという考えは決して好きではないので、1 つのフィールドに格納された区切り文字列は魅力的ではありません... ツリーを使用した隣接パスでは機能する可能性がありますが、それらは常に順序付けられており、タグである必要はありません。これは、それらを見つけるために行う可能性のある LIKE 演算子の作業に負担をかけるようです。

したがって、私の最初の見解は、おそらく Entity -> EntityTag <- Tag です。

  1. このアプローチにより、Tag によるアイテムの検索が非常に簡単になり、EntityTag を介して結合し直すことができます。

  2. 結果セットの個別のタグを選択するには、ここで 2 番目の操作が必要です。したがって、a.) 結果セットを取得し、b.) タグ スペースを正規化します。#1に対する答えが何であれ、これを行うと思います-タグを1つのフィールドに詰め込んでも、タグが重複します(この操作を実行するにはタグを逆シリアル化する必要があります-より多くの作業、完全なリレーショナルの別の引数)アプローチ)。

  3. まだ簡単です。シリアル化されたアプローチがうまく機能する領域の 1 つを次に示します。子タグに参加する必要はありません。エンティティ内にあります。とはいえ、2 つのテーブルの結合を介して 0..n タグを引き出すことは、私にはそれほど難しいことではないようです。パフォーマンスに関する考慮事項について話している場合は、最初に正規化してからビルドし、次にキャッシュまたは denorm を介して最適化します。

もう1つのオプションは、「両方を行う」です。これは時期尚早の最適化のように感じますが、完全に正規化されたアプローチを実行して、タグ中心の操作をサポートし、持続時にシリアライズして、エンティティ内に非正規化バージョンを作成することができます。もう少し作業が必要で、完全にカバーされていないと同期が取れなくなる可能性がありますが、ユースケースで完全に正規化された方法に実際の制限がある場合は、両方の世界が最適です。

Lucene も興味深いものです。インデックス IIRC で特定のメタデータを宣言できるため、この方法でもタグ検索を活用できる可能性があります。私の疑いでは、この道を行き過ぎると、ある時点でデータベースに保存するものとインデックスとの間に切断が発生することになります。私は Lucene について好意的に話すことができます.Lucene は非常に有能で使いやすいです..Text はそれを検索機能に使用し、Community Server に切り替える前はすべての weblogs.asp.net をサポートしていたと思います. MSSQLが画像にない/十分でない場合は、全文検索に固執し、データベースimoのタグの問題を解決します。

于 2008-10-25T14:27:42.477 に答える