Как вы управляете эффективной выборкой данных с помощью вложенных курсоров в схеме relay-esk (с источником данных SQL)?
- Вы пытаетесь сделать один сложный запрос SQL, чтобы решить проблему N + 1 с помощью «LIMIT args_first», «ORDER BY args_orderby» и «WHERE cursor>: args_after»
- Вы запускаете 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, - существует ли хотя бы чистый способ выполнить один запрос и применить
LIMIT
и WHERE createdAt > :after_cursor_val
на уровне вложенности (JOIN)
- Если вышеприведенное возможно, является ли оно более производительным, чем загрузчик данных в масштабе? Поскольку запрос кажется достаточно подробным и сложным, если он будет реализован.
- Что произойдет, если вложенное дерево нумерации страниц будет расти (то есть запросы с 4 вложенными нумерациями страниц)? Будет ли здесь достаточной команда sql на уровне объекта Query? или более масштабируемым является добавление преобразователей в каждое отношение (т. е. книга -> обзоры имеет запрос sql для извлечения всех рецензий этой книги, обзоры -> публикации имеет запрос для извлечения всех конкретных публикаций рецензии, в которых она находилась, и т. д., и пакетируйте их в загрузчик данных)
- если вы идете по маршруту загрузчика данных, пакетная обработка, похоже, использует предложение "WHERE IN" (т. Е.
SELECT * FROM reviews "reviews" WHERE "reviews".bookId IN (...list of book ids batched)
- добавление LIMIT
, ORDER BY
и WHERE createdAt > :cursor
даст неожиданные результаты, так как мой набор результатов является сочетание записей в нескольких «идентификаторах книг»?
- В долгосрочной перспективе, мое личное мнение таково, что чистый SQL-подход будет беспорядочным с точки зрения кода, мысли об этом?