MySQL と PHP のスレッド コメント システムを開発しています。Closure Table パターンを選択しましたが、問題があります。ツリー全体を取得するには、クエリ (クエリ) が必要です。どうやってするか?これについて多くのことを検索しましたが、最適なものが見つかりません。スレッド化されたコメントに適したものがあれば、お知らせください。お返事ありがとうございます。
3 に答える
これは私がこれまでに持っているものです:
SELECT `Comments`.* FROM `Comments`
LEFT JOIN `TreePaths` ON `Comments`.`iD` = `TreePaths`.`descendant`
WHERE `TreePaths`.`ancestor` = <Root ID>
これにより、特定のツリーのすべてのノードがクロージャテーブルからプルされますが、現時点では正しく順序付けられていません。最後の部分がわかれば、この投稿を更新します。プログラム的には、結果セットの情報を使用して正しい順序を取得できますが、結果では正しい順序であることが望ましいです。
このユースケースがアプリケーションで一般的なものである場合は、ルート ID (ツリーのルートの ID。これは、これらのコメントが属する投稿の ID にすることができます) を保存するだけです。コメントのツリー全体を取得する必要がある場合は、次のようにするだけです。
SELECT * FROM comments WHERE root_id = <root_id>
またはあなたの設計のための同等のクエリ。テーブル定義を提供していただければ、特定のクエリについてお手伝いできます。
アップデート:
$dbh = new PDO($dsn, $user, $password);
$sql = "SELECT A.*, GROUP_CONCAT(descendant) as descendants FROM Comments AS A INNER JOIN Paths AS B ON A.id = B.ancestor WHERE A.item = ? GROUP BY A.id";
$stmt = $dbh->prepare($sql);
$stmt->execute(array($item));
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
$adjacency_list = array(); $comments = array();
foreach($data as $row) {
$comments[$row['id']] = $row;
$descendants = explode(',', $row['descendants']);
$adjacency_list[$row['id']] = $descendants;
}
echo '<UL>';
foreach($adjacency_list[$item] as $top_level_comment) {
printTree($top_level_comment, $adjacency_list[$top_level_comment]);
}
echo '</UL>';
function printTree($node, $descendants) {
echo '<LI>'.$node;
if(sizeof($descendants) > 0) {
echo '<UL>';
foreach($descendants as $descendant) {
$d = array();
if(!empty($adjacency_list[$descendant])) $d = $adjacency_list[$descendant];
printTree($descendant, $adjacency_list[$descendant]);
}
echo '</UL>';
}
echo '</LI>';
}
一方、ネストされたセット モデルは、挿入と更新が頻繁に行われるため、コメント システムには適していません。データがめったに更新されない場合、これは効率的なソリューションです。
クロージャーテーブルも見ているので、あなたの質問に出くわしました。Bill Karwin の著書 "Sql anti-patterns" のクロージャ テーブルに関するアドバイスに従えば、問題は解決できると思います。
先祖/子孫の関係を共有するツリー内のノードのペアごとに、このテーブルに 1 つの行を格納します。ツリー内でノードが 複数のレベルで分離されている場合でも同様です。
(私の強調)
したがって、1 回のクエリでparentId
親のすべての子が一度に生成されます。(SQL サーバーでは、これは再帰クエリによって実行できます)。
と:
Closure Table を改善して、直接の親ノードまたは子ノードのクエリをより簡単にすることができます。TreePaths.path_length 属性を Closure Table デザインに追加します。
つまり、アイテム間の距離をクロージャー テーブルに格納します。
あなたは彼の例を本当に気に入ると思います。コメントスレッドについても同様です。