8

オブジェクトのタグ付けにMySQLデータベースを使用するPHP Webアプリケーションがあります。このSOの質問への回答として受け入れられたタグ構造を使用しました。

各タグが一意の親タグを持つことができるタグ階層を実装したいと思います。親タグ T の検索は、T のすべての子孫 (つまり、T、親が T であるタグ (T の子)、T の孫など) に一致します。

これを行う最も簡単な方法は、タグの親タグの ID を含む ParentID フィールドをタグ テーブルに追加するか、タグに親がない場合は何らかのマジック ナンバーを追加することです。ただし、子孫を検索するには、データベースを完全に検索して各「世代」のタグを見つける必要がありますが、これは避けたいと思います。

(おそらく) より高速ですが、正規化されていない方法は、各タグのすべての子、または各タグのすべての子孫を含むテーブルを作成することです。ただし、これにより、データベース内のデータに一貫性がなくなる危険性があります (たとえば、タグが複数の親の子であるなど)。

データを可能な限り正規化しながら、クエリを作成して子孫をすばやく見つける良い方法はありますか?

4

5 に答える 5

9

2つの列を使用して実装しました。タグ名を異なる言語にローカライズする必要があったため、タグ名を別のフィールド/テーブルに保持する必要があったため、ここでは少し単純化します。

  • 鬼ごっこ

たとえば、次の行を見てください。

tag            path
---            ----
database       database/
mysql          database/mysql/
mysql4         database/mysql/mysql4/
mysql4-1       database/mysql/mysql4-1/
oracle         database/oracle/
sqlserver      database/sqlserver/
sqlserver2005  database/sqlserver/sqlserver2005/
sqlserver2005  database/sqlserver/sqlserver2008/

パス フィールドで演算子を使用するlikeと、必要なすべてのタグ行を簡単に取得できます。

SELECT * FROM tags WHERE path LIKE 'database/%'

階層内のノードを移動するときにすべての子も変更する必要があるなど、いくつかの実装の詳細がありますが、難しくはありません。

また、パスの長さが十分であることを確認してください。私の場合、パスにタグ名を使用せず、別のフィールドを使用して、パスが長すぎないようにしました。

于 2008-11-02T16:15:00.350 に答える
2

Ali の回答には、Joe Celko の Trees and Hierarchies in SQL for Smartiesへのリンクがあり、これは私の疑いを裏付けています。すべての世界で最高のものを提供する単純なデータベース構造はありません。私の目的に最適なのは、この本で詳述されている「Frequent Insertion Tree」であると思われます。これは、Ali のリンクの「ネストされたセット モデル」に似ていますが、連続していないインデックスを使用します。これにより、O(1) 挿入 (構造化されていない BASIC の行番号付けのようなもの) が可能になり、必要に応じて時折インデックスを再編成できます。

于 2008-11-02T18:24:26.983 に答える
1

Kimball が Hierarchy Helper Table と呼ぶものを構築できます。

階層が次のようになっているとします: A -> B | B -> C | C -> D

次のようなテーブルにレコードを挿入します

ParentID, ChildID, Depth, Highest Flag, Lowest Flag
A, A, 0, Y, N
A, B, 1, N, N
A, C, 2, N, N
A, D, 3, N, Y
B, B, 0, N, N
B, C, 1, N, N
B, D, 2, N, Y
C, C, 0, N, N
C, D, 1, N, Y
D, D, 0. N, Y

私はそれが正しいと思います....とにかく。ポイントは、階層を正しく保存することです。適切なテーブルからこのテーブルを作成するだけです。このテーブルは、Banshee のようにクエリを実行します。B より下のすべての最初のレベルが何であるかを知りたいとします。

WHERE parentID = 'B' and Depth = 1
于 2008-11-03T17:45:26.953 に答える
1

ここでいくつかの方法

于 2008-11-02T16:19:16.723 に答える
0

子タグを格納するためにある種の配列を使用します。これは、テーブル自体を結合するよりもはるかに高速である必要があります(特に、タグの数が多い場合)。調べてみたところ、mysqlにネイティブ配列データ型があるかどうかはわかりませんが、テキスト列を使用してシリアル化された配列を格納することで、これをエミュレートできます。さらにスピードアップしたい場合は、その列にテキスト検索インデックスを配置して、関連するタグを見つけることができるはずです。

[編集]Aliの記事を読んだ後、私はさらにいくつかのハンティングを行い、postgresで階層を実装するための一連のアプローチに関するこのプレゼンテーションを見つけました。説明の目的でまだ役立つ場合があります。

于 2008-11-02T17:46:59.820 に答える