Разметка GraphQL: курсор против смещения
Нам нужно перестроить бэкэнд-приложение на основе сервисов REST, и поскольку у нас много вложенных уровней в сервисах, мы решили внедрить инновации и попробовать GraphQL.
Мы начали делать простые вещи, и проект выглядит очень многообещающе, однако мы столкнулись с реальными проблемами, такими как нумерация страниц. В REST подход разбиения на страницы был простым, мы используем метод GET с некоторыми параметрами, такими как pageSize
а также pageNumber
(или же offset
) и мы строим SQL-запросы для выполнения этой нумерации страниц.
В GraphQL мы решали проблему, следуя тому же подходу, например, имея такой запрос:
users(size:5 offset:2) {
id
name
}
Этот подход выглядел простым для реализации, однако после углубленного изучения мы обнаружили, что "лучшим" шаблоном для реализации этого является Connection, который будет выглядеть следующим образом:
users(first:2) {
totalCount
edges {
node {
name
}
cursor
}
pageInfo {
endCursor
hasNextPage
}
}
Наши данные хранятся в реляционной базе данных, поэтому я не вижу, как могут помочь курсоры (разве возможно, если я использую идентификатор автоинкремента?).
Почему этот комплексный подход рекомендуется по сравнению с простым? А также, какой курсор и endCursor будут хранить? Я неправильно понимаю что-то на своем пути обучения?
1 ответ
Connection
spec изначально был создан для Relay (клиент GraphQL от Facebook). Позже он разработал собственную жизнь, и теперь считается лучшей практикой, независимо от клиента. Но (и это огромное, но), это определенно не подходит для каждого варианта использования.
Если вы видите ценность в реализации Connection
стиль нумерации страниц, вы всегда можете решить рассматривать курсор как смещение. Например, спецификация определяет 2 аргумента before
а также after
это курсоры. Вы можете просто решить поместить смещение внутрь. 2 других аргумента, first
а также last
, не нужно никакого специального лечения. Логика остается точно такой, как задумано.
Например, вместо
users(size:5 offset:2) { ... } //Get 5 after the first 2
ты получаешь
users(first:5 after:2) { ... } //Get first 5 after the 2nd - exactly the same
Тем не менее, если вы не извлекаете выгоду из Connection
подход, не стесняйтесь игнорировать это. Особенно, если вы даже не используете Relay в качестве клиента. Это совершенно необязательная вещь, и ее не следует подставлять там, где она не принадлежит.