sql - 在 graphQL 服务器中使用 SQL datasarouce 实现嵌套游标分页的最佳方法是什么?
问题描述
您如何管理使用 relay-esk 模式(使用 SQL 数据源)中的嵌套游标的有效数据获取?
- 您是否尝试使用“LIMIT args_first”、“ORDER BY args_orderby”和“WHERE cursor > :args_after”进行单个复杂的 SQL 查询来解决 N+1 问题
- 您是否对数据库运行 2 个查询并使用 facebook 数据加载器?
例如,我有一个架构如下:
enum BookSortKeys {
ID,
TITLE,
PRICE,
UPDATED_AT,
CREATED_AT
}
enum ReviewSortKeys {
ID,
REVIEW,
UPDATED_AT,
CREATED_AT
}
type Book {
id: ID!
title: String!
description: String
price: Float!
updatedAt: String!
createdAt: String!
reviews("""
Returns the elements that come after the specified cursor.
"""
after: String
"""
Returns the elements that come before the specified cursor.
"""
before: String
"""
Returns up to the first `n` elements from the list.
"""
first: Int
"""
Returns up to the last `n` elements from the list.
"""
last: Int
"""
Reverse the order of the underlying list.
"""
reverse: Boolean = false
"""
Sort the underlying list by the given key.
"""
sortKey: ReviewSortKeys = ID): ReviewConnection!
}
type Query {
books("""
Returns the elements that come after the specified cursor.
"""
after: String
"""
Returns the elements that come before the specified cursor.
"""
before: String
"""
Returns up to the first `n` elements from the list.
"""
first: Int
"""
Returns up to the last `n` elements from the list.
"""
last: Int
"""
Supported filter parameters:
- `title`
- `id`
- `price`
- `description`
- `created_at`
- `updated_at`
"""
query: String
"""
Reverse the order of the underlying list.
"""
reverse: Boolean = false
"""
Sort the underlying list by the given key.
"""
sortKey: BookSortKeys = ID): BookConnection!
}
type ReviewConnection {
pageInfo: PageInfo!
edges: [ReviewEdge!]!
}
type ReviewEdge {
cursor: String!
node: Review!
}
type BookConnection {
pageInfo: PageInfo!
edges: [BookEdge!]!
}
type BookEdge {
cursor: String!
node: Book!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
}
type Review {
review: String!
id: ID!
updatedAt: String!
createdAt: String!
}
type Mutation {
}
schema {
query: Query
mutation: Mutation
}
我想执行如下查询并以最有效的方式检索数据。
query GET_BOOKS {
books(first:10, sortKey: PRICE, reverse: true) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
title
description
reviews(after:"base64-cursor" first: 5, sortKey: CREATED_AT) {
edges {
node{
review
}
}
}
}
}
}
}
我可以很容易地将顶部查询(书)的所有分页参数转换为 sql 语句,但是使用嵌套游标,我只能看到 2 个选项(上面提到过)......在实现这些选项之前我面临的当前问题是:
- 如果我采用纯 SQL 方法 - 是否有一种干净的方法来运行单个查询并在嵌套 (JOIN) 级别应用
LIMIT
andWHERE createdAt > :after_cursor_val
- 如果上述是可能的,它是否比大规模的数据加载器性能更高?由于查询似乎如果实施它将非常冗长和复杂。
- 如果嵌套分页树增长(即具有 4 个嵌套分页的请求)会发生什么?一个纯 Query 对象级别的 sql 命令在这里就足够了吗?或者在每个关系上添加解析器是否更具可扩展性(即 book -> reviews 有一个 sql 查询来提取这本书的所有特定评论,reviews -> Publications 有一个查询来提取它所在的所有评论的特定出版物等等在数据加载器中对它们进行批处理)
- 如果你走数据加载器路线,批处理似乎使用“WHERE IN”子句,(即
SELECT * FROM reviews "reviews" WHERE "reviews".bookId IN (...list of book ids batched)
- 会添加LIMIT
,ORDER BY
并WHERE createdAt > :cursor
提供意外结果,因为我的结果集是多个“书籍 ID”的条目混合? - 从长远来看,我个人的感觉是,从代码的角度来看,纯 sql 方法会很混乱,对此有何想法?
解决方案
推荐阅读
- angular - firebase 公司用户登录注册
- delphi - 如何使用 TIdHTTP 在没有表单的情况下登录网页?
- javascript - 如何为这个基于 setInterval 的精灵动画添加 5 秒延迟?
- java - 两行ListView不显示内容
- c - 将 C 结构函数自动桥接到 Swift 方法
- javascript - 如何禁用所有打字稿类型检查?
- javascript - Javascript,从 Firebase 孩子那里获取 autoId
- java - 如何在 Java 8 中填充地图?
- javascript - 如何使用javascript从任何给定格式的输入文件创建图形?
- php - 使用子字符串时出现稀有字符 �