【问题标题】:How to implement GraphQL cursor in SQL query with sort by如何在 SQL 查询中使用 sort by 实现 GraphQL 游标
【发布时间】:2021-05-23 09:08:26
【问题描述】:

我有一个数据库表 reviewsidrating,其中 id 是自动递增的,而 rating 是 0 到 100 之间的整数。

我正在尝试在 GraphQL API 中创建基于光标的分页,但我正在努力为 hasPreviousPagehasNextPage 创建必要的查询。

这是我的数据:

ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 5, RATING: 60

以下是 GQL 查询示例:

reviews(first: 3)

返回

ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20

带有页面信息

hasPreviousPage: false
hasNextPage: true

pageInfo 的查询是

hasPreviousPage = SELECT COUNT(*) > 0 FROM reviews WHERE id < 0;
hasNextPage     = SELECT COUNT(*) > 0 FROM reviews WHERE id > 3;

我的问题是按评级排序时出现的。 进行与之前类似的查询:

reviews(sort: "rating", first: 3)

返回

ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 1, RATING: 50

带有页面信息

hasPreviousPage: false
hasNextPage: true

但是如何像以前一样创建hasPreviousPagehasNextPage 的查询?

hasPreviousPage = SELECT COUNT(*) > 0 FROM reviews WHERE ???
hasNextPage     = SELECT COUNT(*) > 0 FROM reviews WHERE ???

在这种情况下,WHERE 子句应该是什么?子查询是否需要更复杂的查询?我不确定我错过了什么。

【问题讨论】:

    标签: sql postgresql graphql database-cursor


    【解决方案1】:

    您实际上不需要对hasPreviousPagehasNextPage 进行任何数据库查询。 您需要应用 +2 技巧来实现这一点(假设您希望在之前和之后的情况下都实现 hasPreviousPage)。

    假设您有以下查询:

    // `after` should be URL-safe encoded
    // `id` must have a monotonic sort order, a ULID is a fine choice for an id
    // if ULID is not an option for some reason, chose a different column that has a monotonicity to it, e.g. `created_at`
    reviews(first: 3, after: "id:12345;sort_cols:user_id")
    

    您要做的是查询前 5 条评论:

    SELECT *
    FROM reviews
    WHERE id >= ?
    ORDER BY ? ASC;
    
    -- result: 12345, 12346, 12347, 12348, 12349
    -- from the app return (after computing `pageInfo`): 12346, 12347, 12348
    

    如果第一个结果的id与游标中的id匹配,即12345,则表示有前一页。 如果有前一页且返回的行数为 4 或更少,hasNextPage: false。 如果没有上一页并且返回的行数为4或更多,hasNextPage: true

    在返回结果之前,请确保过滤掉与光标 id (12345) 匹配的项目,如果有下一页,则过滤掉一个额外的项目。

    注意必须正确生成 SQL。查询会根据分页的方向而改变(before vs. after)。如果您想支持范围请求,即同时提供 beforeafter 的请求,它也会变得更加复杂。

    例子:

    reviews(first: 3, before: "id:12345;sort_col:user_id")
    

    在这里您要使用降序。 此外,您需要过滤 ids

    SELECT *
    FROM reviews
    WHERE id <= ?
    ORDER BY ? DESC
    LIMIT 5;
    
    -- result: 12345, 12344, 12343, 12342, 12341
    -- from the app return (after computing `pageInfo`): 12344, 12343, 12342
    

    【讨论】:

    • 这个解释得很清楚。非常感谢 Attila,我会尝试这样实现它!
    猜你喜欢
    • 2018-12-09
    • 2018-07-24
    • 1970-01-01
    • 2014-01-22
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 2017-09-25
    相关资源
    最近更新 更多