如何在 SQL 查询中使用排序方式实现 GraphQL 游标
How to implement GraphQL cursor in SQL query with sort by
我有一个数据库 table reviews
id
,rating
其中 id 是自动递增的,rating 是 0 到 100 之间的整数。
我正在尝试在 GraphQL API 中创建基于游标的分页,但正在努力为 hasPreviousPage
和 hasNextPage
.
创建必要的查询
这是我的数据:
ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 5, RATING: 60
下面是一个 GQL 查询示例:
reviews(first: 3)
哪个returns
ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20
有 pageInfo
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)
哪个returns
ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 1, RATING: 50
有 pageInfo
hasPreviousPage: false
hasNextPage: true
但是如何像以前一样为 hasPreviousPage
和 hasNextPage
创建查询?
hasPreviousPage = SELECT COUNT(*) > 0 FROM reviews WHERE ???
hasNextPage = SELECT COUNT(*) > 0 FROM reviews WHERE ???
在这种情况下 WHERE 子句应该是什么?子查询的查询是否需要复杂得多?我不确定我错过了什么。
您实际上不需要 hasPreviousPage
和 hasNextPage
的任何数据库查询。
您需要应用 +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
LIMIT 5;
-- result: 12345, 12346, 12347, 12348, 12349
-- from the app return (after computing `pageInfo`): 12346, 12347, 12348
如果第一个结果的id
与游标中的id相匹配,即12345
则表示有上一页。
如果有上一页且 returned 行数为 4 或更少,hasNextPage: false
。
如果 没有 上一页并且 returned 行数为 4 或更多,hasNextPage: true
.
在 return 结果之前,请确保过滤掉与光标 ID (12345
) 匹配的项目以及如果有下一页则额外的项目。
注意 SQL 必须正确生成。查询将根据分页的方向而改变(before
与 after
)。如果你想支持范围请求,它也会变得更加复杂,即同时提供 before
和 after
的请求。
示例:
reviews(first: 3, before: "id:12345;sort_col:user_id")
这里要使用降序。
此外,您需要过滤 ids <= 来自光标的 id。
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
我有一个数据库 table reviews
id
,rating
其中 id 是自动递增的,rating 是 0 到 100 之间的整数。
我正在尝试在 GraphQL API 中创建基于游标的分页,但正在努力为 hasPreviousPage
和 hasNextPage
.
这是我的数据:
ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 5, RATING: 60
下面是一个 GQL 查询示例:
reviews(first: 3)
哪个returns
ID: 1, RATING: 50
ID: 2, RATING: 80
ID: 3, RATING: 20
有 pageInfo
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)
哪个returns
ID: 3, RATING: 20
ID: 4, RATING: 40
ID: 1, RATING: 50
有 pageInfo
hasPreviousPage: false
hasNextPage: true
但是如何像以前一样为 hasPreviousPage
和 hasNextPage
创建查询?
hasPreviousPage = SELECT COUNT(*) > 0 FROM reviews WHERE ???
hasNextPage = SELECT COUNT(*) > 0 FROM reviews WHERE ???
在这种情况下 WHERE 子句应该是什么?子查询的查询是否需要复杂得多?我不确定我错过了什么。
您实际上不需要 hasPreviousPage
和 hasNextPage
的任何数据库查询。
您需要应用 +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
LIMIT 5;
-- result: 12345, 12346, 12347, 12348, 12349
-- from the app return (after computing `pageInfo`): 12346, 12347, 12348
如果第一个结果的id
与游标中的id相匹配,即12345
则表示有上一页。
如果有上一页且 returned 行数为 4 或更少,hasNextPage: false
。
如果 没有 上一页并且 returned 行数为 4 或更多,hasNextPage: true
.
在 return 结果之前,请确保过滤掉与光标 ID (12345
) 匹配的项目以及如果有下一页则额外的项目。
注意 SQL 必须正确生成。查询将根据分页的方向而改变(before
与 after
)。如果你想支持范围请求,它也会变得更加复杂,即同时提供 before
和 after
的请求。
示例:
reviews(first: 3, before: "id:12345;sort_col:user_id")
这里要使用降序。 此外,您需要过滤 ids <= 来自光标的 id。
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