Reddit のようなコメントをアプリに追加しようとしていますが、データベースの編成にはクロージャー テーブル パターンを使用することにしました。私のアプリデータベースは次のようになります。
投稿
+----+-------+
| id | title |
+----+-------+
| 1 | Hello |
+----+-------+
コメント
+----+-----------+---------+------+
| id | parent_id | post_id | text |
+----+-----------+---------+------+
| 1 | NULL | 1 | ... |
| 2 | 1 | 1 | ... |
| 3 | 2 | 1 | ... |
| 4 | 3 | 1 | ... |
| 5 | 3 | 1 | ... |
| 6 | 5 | 1 | ... |
| 7 | NULL | 1 | ... |
| 8 | 7 | 1 | ... |
| 9 | 4 | 1 | ... |
+----+-----------+---------+------+
コメントパス
+-----------+----------+-------+
| parent_id | child_id | depth |
+-----------+----------+-------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 1 | 2 | 1 |
| 3 | 3 | 0 |
| 2 | 3 | 1 |
| 1 | 3 | 2 |
| 4 | 4 | 0 |
| 3 | 4 | 1 |
| 2 | 4 | 2 |
| 1 | 4 | 3 |
[...snip...]
現在、次のクエリを実行しています。
SELECT c.*, p.*
FROM comments AS c
JOIN comment_paths AS p
ON c.id = p.child_id
WHERE p.parent_id IN
(SELECT c2.id FROM comments AS c2 WHERE c2.parent_id IS NULL AND c2.post_id = 1)
に基づいてコメントのリストを取得しますpost_id
。返されるデータは次のとおりです。
+------+-------------+-----------+--------+-------------+------------+---------+
| c.id | c.parent_id | c.post_id | c.text | p.parent_id | p.child_id | p.depth |
+------+-------------+-----------+--------+-------------+------------+---------+
| 1 | NULL | 1 | ... | 1 | 1 | 0 |
| 2 | 1 | 1 | ... | 1 | 2 | 1 |
| 3 | 2 | 1 | ... | 1 | 3 | 2 |
| 4 | 3 | 1 | ... | 1 | 4 | 3 |
| 5 | 3 | 1 | ... | 1 | 5 | 3 |
| 6 | 5 | 1 | ... | 1 | 6 | 4 |
| 9 | 4 | 1 | ... | 1 | 9 | 4 |
| 7 | NULL | 1 | ... | 7 | 7 | 0 |
| 8 | 7 | 1 | ... | 7 | 8 | 1 |
+------+-------------+-----------+--------+-------------+------------+---------+
これはツリーを表します:
[1]
|[2]
| |[3]
| |[4]
| | |[9]
| [5]
| |[6]
[7]
|[8]
ただし、返されたデータを Python ツリー構造に変換するのに苦労しています。基本的に、私の目標はこの質問と最終出力(HTML)に関するこの質問ですが、すでに情報を持っているので、再帰SQLステートメントに頼りたくありません。これに似た構造になりたいので、ある種の再帰が必要だと思います:
[
{
'id': 1,
...
'children': [
{
'id': 2,
...
'children': [ ... ]
}
]
},
{
'id': 7,
...
'children': [
{
'id': 8,
...
}
]
}
]
基本的に辞書のネストされたリストなので、Jinja の再帰 loopを使用してそれらをループできます。誰にもアイデアはありますか?
ありがとう!
編集 2013-04-17
いじって、私は「実用的な」解決策を持っていますが、それは多くの反復を行うので、この質問に対する答えとしてマークしたくありません。私が使用した解決策は次のとおりです。
comment_set = ... # previous query to grab data set
def create_tree(parent):
parent['children'] = []
for record in comment_set:
if record['parent_id'] == parent['id']:
parent['children'].append(create_tree(record))
return parent
comment_tree = []
for record in comment_set:
if record['parent_id'] is None: # if this is the start of a tree
comment_tree.append(create_tree(record))
セット内のすべてのレコードが呼び出されるcomment_set
たびに繰り返されるため、理想的ではありません。create_tree()
しかし、それは私が今持っている最高のものです。誰にも考えはありますか?