24

Tôi đang phát triển một ứng dụng web có thể hỗ trợ nhận xét theo chuỗi. Tôi cần khả năng sắp xếp lại các bình luận dựa trên số phiếu bầu nhận được. (Giống với cách nhận xét của chuỗi hoạt động trong reddit)Tôi làm cách nào để triển khai nhận xét theo chuỗi?

Tôi rất muốn nghe ý kiến ​​của cộng đồng SO về cách thực hiện.

Tôi nên thiết kế các bình luận bảng như thế nào? Đây là cấu trúc tôi đang sử dụng ngay bây giờ:

Comment 
    id 
    parent_post 
    parent_comment 
    author 
    points 

Cần thực hiện những thay đổi gì cho cấu trúc này?

Tôi nên lấy chi tiết từ bảng này để hiển thị chúng theo cách chính xác như thế nào? (Thực hiện bằng bất kỳ ngôn ngữ nào đều được chào đón. Tôi chỉ muốn biết cách thực hiện theo cách tốt nhất có thể)

Tôi cần phải cẩn thận khi thực hiện tính năng này để ít tải CPU hơn/Cơ sở dữ liệu?

Xin cảm ơn trước.

Trả lời

14

Lưu trữ cây trong cơ sở dữ liệu là chủ đề có nhiều giải pháp khác nhau. Nó phụ thuộc vào nếu bạn muốn lấy ra một subhierarchy (vì vậy tất cả trẻ em của item X) hoặc nếu bạn chỉ muốn lấy toàn bộ các phân cấp và xây dựng cây theo cách O (n) trong bộ nhớ bằng cách sử dụng một từ điển.

Bảng của bạn có lợi thế là bạn có thể tìm nạp tất cả các nhận xét về bài đăng trong 1 lần, bằng cách lọc trên bài đăng chính. Khi bạn đã định nghĩa cha mẹ của chú thích trong sách giáo khoa/ngây thơ, bạn phải xây dựng cây trong bộ nhớ (xem bên dưới). Nếu bạn muốn để có được những cây từ DB, bạn cần một cách khác để lưu trữ một cây: Xem mô tả của tôi về một cách tiếp cận trước calc dựa ở đây: http://www.llblgen.com/tinyforum/GotoMessage.aspx?MessageID=17746&ThreadID=3208 hoặc bằng using balanced trees described by CELKO here:

hoặc chưa tiếp cận khác: http://www.sqlteam.com/article/more-trees-hierarchies-in-sql

Nếu bạn tìm nạp mọi thứ trong phân cấp trong bộ nhớ và xây dựng cây ở đó, nó có thể hiệu quả hơn do truy vấn khá đơn giản: chọn .. từ Nhận xét nơi ParentPost = @id ORDER BY ParentComment ASC

Sau truy vấn đó, bạn buil d cây trong bộ nhớ chỉ với 1 từ điển mà theo dõi các CommentID tuple - Bình luận. Bây giờ bạn đi qua các resultset và xây dựng cây trên bay: mỗi bình luận bạn chạy vào, bạn có thể tra cứu parentcomment của nó trong từ điển và sau đó lưu trữ các bình luận hiện đang xử lý cũng trong từ điển đó.

+0

Bởi "trong bộ nhớ", bạn có ý nghĩa ở cấp ứng dụng không? – Ced

3

thiết kế hiện tại của bạn về cơ bản là tốt cho hệ thống phân cấp nhỏ (ít hơn ngàn bài)

Nếu bạn muốn lấy về mặt kĩ certian hoặc chiều sâu, thêm một 'mức' mục để cấu trúc của bạn và tính toán nó như là một phần của cứu

Nếu hiệu suất là một vấn đề sử dụng một bộ nhớ cache phong nha

+0

Tôi không hiểu cấp độ? –

3

tôi muốn thêm các lĩnh vực mới sau vào tabel trên:

  • thread_id: nhận dạng cho tất cả các bình luận gắn liền với một đối tượng cụ thể

  • date: ngày bình (cho phép lấy các ý kiến ​​theo thứ tự)

  • bậc: nhận xét thứ hạng (cho phép lấy theo thứ tự bình luận bằng cách xếp hạng)

Sử dụng các lĩnh vực này bạn sẽ có thể:

  1. lấy tất cả các bình luận trong một thread trong một op đơn
  2. nhận xét đơn đặt hàng theo chuỗi hoặc theo ngày hoặc xếp hạng

Thật không may nếu bạn muốn duy trì các truy vấn của mình gần tiêu chuẩn SQL, bạn sẽ phải tạo lại cây trong bộ nhớ. Một số DBS đang cung cấp các truy vấn đặc biệt cho dữ liệu phân cấp (fe Oracle)

./alex

+0

Alex, cảm ơn câu trả lời, nhưng tôi không hiểu một số điểm của bạn. Tôi nghĩ thread_id giống như post_id, ngày có thể được thay thế bằng id tăng tự động, rank = points. Đó là những gì tôi đã làm trong thiết kế của tôi. Bạn có thể làm rõ bất kỳ sự khác biệt b/w thiết kế của tôi và thiết kế được đề xuất? – Niyaz

+0

@Niyaz: Tôi đoán bạn có thể cần phải chỉnh sửa câu hỏi của bạn vì tôi không thấy một post_id (và thực sự là tôi hiểu lầm điểm). thread_id: id duy nhất cho tất cả các nhận xét trong một chuỗi (được đính kèm với một phần conent). autoincrement có thể cung cấp thứ tự nhưng không tương đương với một ngày (kiểm tra gần như tất cả các diễn đàn). – alexpopescu

+0

Tôi đã nhầm lẫn. Nếu "parent_comment" trỏ đến id nhận xét của cha mẹ, tôi sẽ đặt tên là "parent_comment_id" để xóa không khí. Tôi không chắc chắn "parent_post" có nghĩa là gì và tại sao nó khác với "parent_comment". –

4

Couple điều cũng cần xem xét ...

1) Khi bạn nói "loại như reddit" dựa trên xếp hạng hoặc ngày, bạn có nghĩa là cấp cao nhất hoặc toàn bộ điều?

2) Khi bạn xóa nút, điều gì sẽ xảy ra với các nhánh? Bạn có tái bố mẹ họ không? Trong quá trình thực hiện, tôi nghĩ rằng các biên tập viên sẽ quyết định - hoặc là ẩn nút và hiển thị nó là "bình luận ẩn" cùng với các trẻ em có thể nhìn thấy, ẩn các bình luận và đó là trẻ em, hoặc nuke toàn bộ cây. Việc làm cha mẹ trở nên dễ dàng (chỉ cần đặt cha mẹ của con cái vào cha mẹ đã bị xóa), nhưng nó liên quan đến toàn bộ cây có vẻ phức tạp để thực hiện trong cơ sở dữ liệu.

Tôi đã xem xét mô-đun ltree cho PostgreSQL. Nó sẽ làm cho các hoạt động cơ sở dữ liệu liên quan đến các bộ phận của cây nhanh hơn một chút. Về cơ bản, điều này cho phép bạn thiết lập một trường trong bảng trông giống như:

ltreetest=# select path from test where path <@ 'Top.Science'; 
       path     
------------------------------------ 
Top.Science 
Top.Science.Astronomy 
Top.Science.Astronomy.Astrophysics 
Top.Science.Astronomy.Cosmology 

Tuy nhiên, nó không đảm bảo tính toàn vẹn tham chiếu. Nói cách khác, bạn có thể có một bản ghi cho "Top.Science.Astronomy" mà không có bản ghi cho "Top.Science" hoặc "Top". Nhưng những gì nó cho phép bạn làm là những thứ như:

-- hide the children of Top.Science 
UPDATE test SET hide_me=true WHERE path @> 'Top.Science'; 

hoặc

-- nuke the cosmology branch 
DELETE FROM test WHERE path @> 'Top.Science.Cosmology'; 

Nếu kết hợp với "comment_id" truyền thống/"PARENT_ID" cách tiếp cận sử dụng thủ tục lưu trữ, tôi nghĩ bạn có thể nhận tốt nhất của cả hai thế giới.Bạn có thể nhanh chóng duyệt cây nhận xét trong cơ sở dữ liệu bằng cách sử dụng "đường dẫn" của bạn và vẫn đảm bảo tính toàn vẹn tham chiếu qua "comment_id"/"parent_id". Tôi hình dung một cái gì đó như:

CREATE TABLE comments (
comment_id SERIAL PRIMARY KEY, 
parent_comment_id int REFERENCES comments(comment_id) ON UPDATE CASCADE ON DELETE CASCADE, 
thread_id int NOT NULL REFERENCES threads(thread_id) ON UPDATE CASCADE ON DELETE CASCADE, 
path ltree NOT NULL, 
comment_body text NOT NULL, 
hide boolean not null default false 
); 

Chuỗi con đường cho một cái nhìn bình luận như được

<thread_id>.<parent_id_#1>.<parent_id_#2>.<parent_id_#3>.<my_comment_id> 

Vì vậy, một lời nhận xét gốc rễ của chủ đề "102" với một comment_id "1" sẽ có một con đường của:

102.1

Và một đứa trẻ mà comment_id là "3" sẽ là:

102.1.3

Một số trẻ em của "3" có id của "31" và "54" sẽ là:

102.1.3.31 
102.1.3.54 

Để ẩn nút "3" và những đứa trẻ của mình, bạn muốn phát hành này :

UPDATE comments SET hide=true WHERE path @> '102.1.3'; 

Tôi không biết - điều này có thể làm tăng thêm chi phí không cần thiết. Thêm vào đó tôi không biết ltree được duy trì tốt như thế nào.

Các vấn đề liên quan