Phân trang khó khi xếp hạng nội dung của bạn có thể thay đổi nhanh chóng và thậm chí khó hơn khi những thứ hạng này khác nhau cho mỗi người dùng. (Hãy xem cuộn vô hạn như một kiểu phân trang nơi các liên kết không nhìn thấy được.) Có hai vấn đề khó khăn: nội dung mới được thêm vào ở trên cùng và nội dung được kiểm tra lại.Sơ đồ phân trang nào có thể xử lý danh sách nội dung thay đổi nhanh chóng?
Hãy quên nội dung mới thêm và chấp nhận rằng bạn sẽ phải làm mới trang 1 để xem nội dung đó. Chúng ta cũng giả vờ chúng ta đang làm thuần túy ORDER BY position
; nếu bạn đang đặt hàng bởi một cái gì đó khác, bạn có thể phải sử dụng chức năng cửa sổ. Các trang của chúng tôi có 4 hàng động vật trên mỗi trang. Chúng bắt đầu:
+----+----------+-----------+
| id | position^| animal |
+----+----------+-----------+
| 1 | 1 | Alpacas |
| 2 | 2 | Bats |
| 3 | 3 | Cows |
| 4 | 4 | Dogs |
| 5 | 5 | Elephants |
| 6 | 6 | Foxes |
| 7 | 7 | Giraffes |
| 8 | 8 | Horses |
+----+----------+-----------+
Sau khi tìm nạp trang 1 và trước khi tìm nạp trang 2, rất nhiều mục di chuyển xung quanh. DB bây giờ là:
+----+----------+-----------+
| id | position^| animal |
+----+----------+-----------+
| 4 | 1 | Dogs |
| 2 | 2 | Bats |
| 1 | 3 | Alpacas |
| 5 | 4 | Elephants |
| 6 | 5 | Foxes |
| 7 | 6 | Giraffes |
| 3 | 7 | Cows |
| 8 | 8 | Horses |
+----+----------+-----------+
Có ba cách tiếp cận chung:
phương pháp offset/hạn
Đây là phương pháp ngây thơ tiêu biểu; trong Rails, đó là cách hoạt động của will_paginate và Kaminari. Nếu tôi muốn tìm nạp trang 2, tôi sẽ làm
SELECT * FROM animals
ORDER BY animals.position
OFFSET ((:page_num - 1) * :page_size)
LIMIT :page_size;
được xếp hàng 5-8. Tôi sẽ không bao giờ thấy Voi, và tôi sẽ thấy Bò hai lần.
cuối nhìn thấy cách tiếp cận ID
Reddit có một cách tiếp cận khác nhau. Thay vì tính toán hàng đầu tiên dựa trên kích thước trang, ứng dụng khách sẽ theo dõi ID của mục cuối cùng mà bạn đã thấy, chẳng hạn như dấu trang. Khi bạn nhấn "tiếp theo", họ bắt đầu tìm kiếm từ dấu trang đó trở đi:
SELECT * FROM animals
WHERE position > (
SELECT position FROM animals
WHERE id = :last_seen_id
)
ORDER BY position
LIMIT :page_size;
Trong một số trường hợp, điều này hoạt động tốt hơn so với trang/bù. Nhưng trong trường hợp của chúng tôi, Chó, bài viết được nhìn thấy lần cuối, đã phóng to sang phải # 1. Vì vậy, khách hàng gửi lên ?last_seen_id=4
và trang 2 của tôi là Dơi, Alpacas, Voi và Cáo. Tôi đã không bỏ lỡ bất kỳ động vật nào, nhưng tôi thấy Bats và Alpacas hai lần.
trạng thái Server side
HackerNews (và trang web của chúng tôi, ngay bây giờ) giải quyết này với continuations server-side; họ lưu trữ toàn bộ toàn bộ kết quả được đặt cho bạn (hoặc ít nhất một vài trang trước?) và liên kết "Thêm" liên quan đến việc tiếp tục đó. Khi tôi tìm nạp trang 2, tôi yêu cầu "trang 2 của truy vấn ban đầu của tôi". Nó sử dụng cùng một tính toán bù đắp/giới hạn, nhưng vì nó chống lại truy vấn ban đầu, tôi chỉ đơn giản là không quan tâm rằng mọi thứ bây giờ đã di chuyển xung quanh. Tôi thấy Voi, Cáo, Hươu cao cổ và Ngựa. Không có dups, không có mặt hàng bị mất.
Nhược điểm là chúng tôi phải lưu trữ nhiều trạng thái trên máy chủ. Trên HN, nó được lưu trong RAM, và trong thực tế những sự tiếp tục này thường hết hạn trước khi bạn có thể nhấn nút "Thêm", buộc bạn phải quay trở lại trang 1 để tìm một liên kết hợp lệ. Trong hầu hết các ứng dụng, bạn có thể lưu trữ nó trong memcached, hoặc thậm chí trong chính cơ sở dữ liệu (sử dụng bảng của riêng bạn, hoặc trong Oracle hoặc PostgreSQL, sử dụng các con trỏ có thể giữ). Tùy thuộc vào ứng dụng của bạn, có thể có một hit hiệu suất; trong PostgreSQL, ít nhất, bạn phải tìm cách để nhấn lại kết nối cơ sở dữ liệu đúng, đòi hỏi nhiều trạng thái dính hoặc một số định tuyến back-end thông minh.
Đây có phải là ba cách tiếp cận duy nhất có thể không? Nếu không, có khái niệm khoa học máy tính nào sẽ cho tôi nước ép Google đọc về điều này không? Có cách nào để ước tính phương pháp tiếp cận mà không lưu trữ toàn bộ tập kết quả không? Về lâu dài, có hệ thống sự kiện truyền trực tuyến/điểm-thời gian phức tạp, trong đó "tập hợp kết quả của thời điểm tôi tìm nạp trang 1" là vĩnh viễn có thể lấy được. Ngắn gọn ...?
Tôi khuyên bạn nên xem xét nó từ một góc độ khác. Có thể tránh được phân trang - chỉ cần sử dụng cuộn vô hạn + một số tập lệnh mở rộng cập nhật danh sách mà không cần tải lại trang và hiển thị biểu tượng ↑/↓ thích hợp để thuận tiện cho người dùng. Nó phụ thuộc vào trường hợp sử dụng của bạn, mặc dù. Cập nhật: FWIW, đây là [câu hỏi liên quan] (http://ux.stackexchange.com/questions/2997/best-way-to-add-items-to-a-paginated-list/2999#2999) từ UX StackExchange . – Tony
Vâng, điều đó không hiệu quả đối với trường hợp sử dụng của chúng tôi ... mọi thứ liên tục được điều chỉnh lại và bạn sẽ không muốn màn hình được cập nhật liên tục. Ý tưởng tuyệt vời, mặc dù. –
Bạn có thể lưu trữ trạng thái trên máy khách và gửi tất cả các id của các bản ghi đã xem. –