ソーシャル メディアとコンテンツ プラットフォームの台頭により、マルチレベルのコメント システムは、さまざまなプラットフォームがユーザーやコミュニティと対話するための重要な方法になりました。マルチレベルのコメント システムをフロントエンドに実装するのは比較的簡単ですが、バックエンドに実装するのは比較的複雑です。この記事では、golangを使って多段コメントを実装する方法を紹介します。
複数レベルのコメントは実際にはツリー構造の表示であり、各コメントはノードとして使用できます。マルチレベルレビューシステムは、ツリー構造の基本データ構造であるツリーおよびバイナリツリーを使用して実装できます。この記事では、実装にツリー構造のバイナリ ツリーを使用することを選択します。
バイナリ ツリーのノードは左右 2 つの子ノードで構成され、左のノードは現在のノードの最初の子ノード、右のノードは現在のノードの 2 番目の子ノードです。したがって、コメントを追加するたびに、現在のコメントの親ノードとその左右の子ノードに注意するだけで済みます。
マルチレベルのコメント システムを実装するには、各コメントの親子関係をデータベースに保存する必要があります。一般に、ツリー構造を保存するには 2 つの方法を使用できます。
この記事では、2 番目の方法である、単一のテーブルで自己参照リレーションシップを使用することを選択します。
コメント テーブル (コメント) の構造は次のとおりです。
CREATE TABLE `comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL COMMENT '父级评论id', `content` varchar(255) DEFAULT NULL COMMENT '评论内容', `created_at` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`), CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `comment` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='评论表'
上記のテーブル構造において、parent_id
は現在のコメントの親ノード ID を表します。現在のコメントが第 1 レベルのコメントである場合、parent_id
は null になります。 id
は現在のコメントの ID、content
はコメントの内容、created_at
は作成時刻です。
まず、golang でデータベース/sql ドライバーと mysql ドライバーを使用してデータベースにリンクする必要があります:
dsn := "root:123456@tcp(127.0.0.1:3306)/test" db, err := sql.Open("mysql", dsn) if err != nil { fmt.Printf("mysql connect error %s", err.Error()) return }
コメントを挿入するときは、現在のコメントを親ノードとして処理するか子ノードとして処理するかを決定する必要があります。
現在のコメントが親ノードとして使用されている場合は、データベースに直接挿入されます。現在のコメントが子ノードの場合は、親ノードの右側のノードを更新する必要があります。
// 添加评论 func AddComment(comment Comment) error { if comment.ParentID == 0 { _, err := db.Exec("INSERT INTO comment(parent_id, content, created_at) VALUES(?, ?, ?)", nil, comment.Content, comment.CreatedAt) if err != nil { return err } } else { var rightNode *int err := db.QueryRow("SELECT right_node FROM comment WHERE id = ?", comment.ParentID).Scan(&rightNode) if err != nil { return err } tx, err := db.Begin() if err != nil { return err } // 更新右节点 _, err = tx.Exec("UPDATE comment SET right_node = right_node + 2 WHERE right_node > ?", rightNode) if err != nil { tx.Rollback() return err } _, err = tx.Exec("UPDATE comment SET left_node = left_node + 2 WHERE left_node > ?", rightNode) if err != nil { tx.Rollback() return err } _, err = tx.Exec("INSERT INTO comment(parent_id, left_node, right_node, content, created_at) VALUES(?, ?, ?, ?, ?)", comment.ParentID, rightNode, rightNode+1, comment.Content, comment.CreatedAt) if err != nil { tx.Rollback() return err } tx.Commit() } return nil }
コメントをクエリするときは、ノードを左と右の順序で並べ替えて、ツリー構造のコメント リストを取得する必要があります。コメントをクエリする場合、ソートに左右のノードを使用する必要があるため、クエリ条件に左右のノード列を追加する必要があります。さらに、フロントエンド表示を容易にするために、レベル フィールドを使用して現在のノードがノードのどのレベルであるかを示す必要もあります。
type Comment struct { ID int `json:"id"` ParentID int `json:"parent_id"` Content string `json:"content"` LeftNode int `json:"left_node"` RightNode int `json:"right_node"` Level int `json:"level"` CreatedAt string `json:"created_at"` } // 获取评论列表 func GetComments() ([]Comment, error) { rows, err := db.Query("SELECT id, parent_id, content, created_at, left_node, right_node, (COUNT (parent.id) -1) AS level FROM comment AS node, comment AS parent WHERE node.left_node BETWEEN parent.left_node AND parent.right_node GROUP BY node.id ORDER BY left_node") if err != nil { return nil, err } defer rows.Close() var comments []Comment for rows.Next() { var comment Comment err := rows.Scan(&comment.ID, &comment.ParentID, &comment.Content, &comment.CreatedAt, &comment.LeftNode, &comment.RightNode, &comment.Level) if err != nil { return nil, err } comments = append(comments, comment) } return comments, nil }
コメントを削除するときは、現在のコメントが親ノードであるか子ノードであるかを判断する必要があります。親ノードの場合は、コメント全体を削除する必要があります。サブツリー。
// 删除评论 func DeleteComment(id int) error { tx, err := db.Begin() if err != nil { return err } var leftNode int var rightNode int err = tx.QueryRow("SELECT left_node, right_node FROM comment WHERE id = ?", id).Scan(&leftNode, &rightNode) if err != nil { tx.Rollback() return err } if leftNode == 1 && rightNode > 1 { // 删除子树 _, err = tx.Exec("DELETE FROM comment WHERE left_node >= ? AND right_node <= ?;", leftNode, rightNode) if err != nil { tx.Rollback() return err } err = tx.Commit() if err != nil { tx.Rollback() return err } } else { // 删除单个节点 _, err = tx.Exec("DELETE FROM comment WHERE id = ?", id) if err != nil { tx.Rollback() return err } err = tx.Commit() if err != nil { tx.Rollback() return err } } return nil }
上記のコード実装を通じて、完全に機能するマルチレベル コメント システムを迅速に構築できます。もちろん、これは基本的な実装方法にすぎず、実際のシナリオでは、特定のニーズに応じて対応する最適化や拡張を行う必要があります。
以上がGolang はマルチレベルのコメントを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。