我有一个帖子表。我想查询这些帖子作为页面。因为我想让我的端点保持无状态,所以我想用offset和limit这样做:
SELECT * FROM post LIMIT 50 OFFSET $1 ORDER BY id
其中$1是页码乘以页面大小(50)。检查我们是否已经完成的简单方法是看我们是否退回了50页。当然,问题是如果页数能被50整除,我们就不能确定了。
到目前为止,我解决这个问题的方法是每个查询简单地获取51个帖子,页面大小仍然是50。这样,如果返回的查询小于51,我们就到达了结束。
不幸的是,这似乎是一种非常粗糙的方法。所以我想知道,pg-promise或postgresql中是否有一些功能可以表明我已经达到了表的末端,而不需要诉诸这样的技巧?
我发现开销最小的最简单方法:
您可以在每个页面请求中请求pageLimit+1
行。在您的控制器中,您将检查rowsCount > pageLimit
,并将知道有更多的可用数据。当然,在返回行之前,您需要删除最后一个元素并沿着行发送类似hasNext
布尔值的东西。
对于DB来说,检索额外的数据行通常比计算所有行或对page+1
进行额外请求以检查是否返回任何行更便宜。
没有直接的内置过程。但是你可以计算行数并把它加到结果中。你甚至可以给用户条目数或页数:
-- Item count
with pc(cnt) as (select count(*) from post)
select p.*, cnt
from post p
cross join pc
limit 50 offset $1;
-- page count
with pc(cnt) as (select count(*)/50 + ((count(*)%50)>0)::int from post)
select p.*, cnt
from post p
cross join pc
limit 50 offset $1;
注意:计数函数可能很慢,即使没有,它也会增加响应时间。额外的开销值得吗?只有你和用户才能回答这个问题。
此方法仅在特定设置下有效(带有网络请求缓存的SPA以及希望通过预取使分页感觉更快):
对于每个页面,您发出两个请求:一个请求当前页面数据,一个请求下一页数据。
它可以工作,如果你使用一个React单页应用程序与react-query
,其中nextPage
不会被重新获取,但当用户打开它时重用。
否则,如果不重用nextPage
,则比检查总行数以确定是否有剩余行更糟糕,因为您将为每个页面发出2个请求。
它甚至会使用户界面更快捷,因为切换到下一页总是即时的。
如果你有很多页面转换,这个方法会很好地工作,因为调用的总数等于numberOfPages+1,所以如果平均用户去10个页面,numberOfPages+1=10+1或只有10%的开销。但是,如果您的用户通常不会超过第一页,那么在这种情况下numberOfPages+1=2调用单个页面就没有什么意义了。