我在这些表上实现了键集分页
CREATE TABLE profiles (
id serial primary key,
username varchar(255),
followers bigint,
tsv tsvector
);
CREATE TABLE profile_categories (
username varchar(255),
category varchar(255),
primary key (username, category)
);
使用以下查询:
SELECT profiles.*, categories,
ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers) AS rank
FROM profiles
JOIN plainto_tsquery($1) AS q ON tsv @@ q
LEFT OUTER JOIN profile_categories ON profiles.username = profiles_categories.username
WHERE followers IS NOT NULL AND
followers > 0 AND
(ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers), -id) < ($2, $3)
ORDER BY (
ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers),
-id
) DESC
LIMIT 50;
这个想法是使用ts_rank_cd
全文搜索查询对文档进行排名,并通过关注者的对数来缩放排名。
$2
问题是,当我通过提供上一页的最后排名和 id (和)查询第二页时$3
,我仍然从上一页得到最后一个结果作为第一个结果(所以我实际上只得到 49 个新结果) !我不知道这是怎么可能的,因为我使用的是严格的不等式运算符。
编辑即使我decimal
对相同的问题进行排名 - 我在一页的末尾和下一页的开头得到重复的结果:
SELECT profiles.*, categories,
(ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers))::decimal AS rank
FROM profiles
JOIN plainto_tsquery($1) AS q ON tsv @@ q
WHERE followers IS NOT NULL AND
followers > 0 AND
((ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers))::decimal, -id) < ($2, $3)
ORDER BY (
(ts_rank_cd(tsv, plainto_tsquery($1)) * log(followers))::decimal,
-id
) DESC
LIMIT 50
浮点数容易出现表示/舍入错误。当翻译给客户并再次翻译回来时,它不太可能与原文完全相同。
我通过明确排除与最后一次看到的 id 对应的 id 解决了这个问题(添加以粗体突出显示):