限制每个用户每个查询返回的条目

时间:2021-03-03 13:34:44

标签: node.js postgresql

我有以下请求:

let artPerCall = 20
let artPerUser = 2
let start = req.params.page

let query = `
    SELECT * from 
    (
        SELECT a.*, row_to_json(u.*) as userinfo,
            row_number() over (partition by u.address order by a.date desc) as ucount
        FROM artworks a INNER JOIN users u ON a.address = u.address 
        WHERE a.flag != ($1) OR a.flag IS NULL
    ) t
    WHERE ucount <= ($2)
    ORDER BY date DESC 
    LIMIT ${artPerCall} OFFSET ${(start-1) * artPerCall}`

pool.query(query, ["ILLEGAL", artPerUser])
    .then(users => {
        if (users) {
            res.json(users.rows);
        }
    })
    .catch(err => {
        next(err);
    })

通过具有以下路径的 API 调用 /artworks/paginate/1/20 where (/artworks/paginate/{page}/20)

预期结果是每次调用获得 20 个结果,每个用户最多 2 个条目。

当前结果: 似乎它按预期只为每个用户返回 2 个条目,但是一旦它为某个页面上的用户返回 2 个条目,那么即使他们有条目,也不会在随后的页面中为同一用户返回更多结果。

知道我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

<块引用>

似乎它按预期只为每个用户返回 2 个条目,但是一旦它为某个页面上的用户返回 2 个条目,那么即使他们有条目,在随后的页面中也不会为同一用户返回结果。

正确,这就是查询的作用。它选择:

row_number() over (partition by u.address order by a.date desc) as ucount
...
WHERE ucount <= ($2)

如果参数 $2 在您的示例代码中设置为 2,那么在排序和分页之前,它将为每个用户选择 2 个条目,而不是更多。如果用户有更多条目,它们将被过滤掉。

如果您删除“WHERE ucount <= ($2)”,那么您只会得到按日期排序的所有结果,但这听起来不像您想要的。

但是,我认为您想要实现的目标听起来有点复杂。我不确定这对可用性是否有好处,因为结果对用户来说看起来很随机。因此,您需要使用示例数据准确描述您想要的内容。

例如,如果您想避免一个用户发布大量相同日期的项目将所有其他用户推到搜索结果中,那么限制每个用户的结果数量是一个好主意,但也许是一个按钮“来自该用户的更多...”比将用户的项目向下推送到下一页更好的选择。

假设您只有两个用户,user1 发布了日期为“今天”的 20 个项目,而 user2 昨天发布了 10 个项目。您是否想要 user1 的 2 个项目,然后是 user2 的 2 个项目,然后是 user1 的 18 个剩余项目,然后是 user 的 8 个剩余项目?或者它们会在某种程度上相互交错,这会使结果中的日期顺序有点随机?

编辑

这是一个建议:

SELECT * from 
(
    SELECT *, 
        row_number() over (partition by user_id order by date desc) as ucount
    FROM artworks
) t
ORDER BY (ucount/3)::INTEGER ASC, date DESC 
LIMIT 20 OFFSET 0;

"(ucount/3)::INTEGER"每个用户的前两幅作品为0,接下来的3幅为1,接下来的3幅为2,依此类推,所以每个用户最近的2幅作品结束先上,然后是每个用户最近的3件作品,以此类推。

另一个:

ORDER BY ucount<3 ASC, date DESC 

这将把每个用户最近的 2 幅作品放在最前面,然后其余的只是按日期排序。

相关问题