В GraphQL, как управлять запросом БД по запросу клиента?

Я учусь использовать GraphQL в эти дни. На мой взгляд, чтобы построить запрос, мне нужно построить три части:

  1. Схема
type User{
  id String
  name String
  cars [Car!]!
}
type Car{
  id String
}
type Query{
  user(id: String): User
}
  1. Функция запроса БД
{
  user: async function ({id}) {
    const user = await DB.user.findOne({id});
    const userCars = await DB.car.find({userId: id});
    user.cars = userCars;
    return cars;
  }
}
  1. Клиентский запрос
{
  user (id: "1") {
    name
    cars {
      id
    }
  }
}

Этот запрос возвращает имя пользователя и его автомобили. Функция запроса БД всегда запрос для автомобилей.

Но иногда мне просто нужна информация о пользователе:

{
  user (id: "1") {
    name
  }
}

Я не хочу запрашивать автомобили, поэтому я надеюсь, что моя функция запроса БД может автоматически выбирать, запрашивать автомобили или нет.

Как я могу это сделать?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
0
0
146
3

Ответы 3

GraphQL.js будет поддерживать либо свойства объекта, либо методы для функций преобразователя; это обсуждается на его странице Типы объектов.

Один из способов справиться с этим — просто вставить анонимную функцию непосредственно в возвращаемый объект:

{
  user: async function ({id}) {
    const user = await DB.user.findOne({id});
    user.cars = () => DB.car.find({userId: id});
    return cars;
  }
}

Другой способ — создать объект-оболочку с классом, который предоставляет свойство id и (асинхронный, ленивый) метод cars; некоторые примеры этого находятся в Документация GraphQL.js. Этот подход работает в большинстве реализаций GraphQL на большинстве языков.

Элегантное решение. Сэкономьте мое время, чтобы написать «если»!

pingze 05.03.2019 13:51

Я думаю, вы изучаете автоматическое создание/отображение запроса GraphQL в запрос БД.

Все запросы зависят от базы данных/проекта, поэтому вы должны создать это сопоставление. Вы можете легко сделать это с пакетом графические поля.

Скопирован раздел ПОЧЕМУ из пакета:

An underlying REST api may only return fields based on query params.

{
  user {
    profile {
      firstName
    },
    id
  }
}

should request /api/user?fields=profile,id

while

{
  user {
    email
  }
}

should request /api/user?fields=email Implement your resolve method like so:

resolve(root, args, context, info) {
    const topLevelFields = Object.keys(graphqlFields(info));
    return fetch(`/api/user?fields=${topLevelFields.join(',')}`);
}

Спасибо, это более прямое решение. Я просмотрел "информацию", но не нашел то, что мне нужно. Этот модуль полезен!

pingze 05.03.2019 13:50

Лучше не сжимать все это в одну функцию преобразователя. Вместо этого создайте отдельный ObjectType для Cars, который имеет свои собственные поля и собственную функцию разрешения. Таким образом, запрос автомобиля вызывается только в том случае, если запрашивается это поле.

Если вы используете RDS, присоединяйтесь к монстру и громче данных, это может помочь оптимизировать производительность ваших запросов.

  • Присоединяйтесь к монстру, который основан на создании одного большого запроса на соединение, а также решает проблему запроса только тех полей, которые вам нужны из БД.
  • Кэшированный и пакетный источник данных SQL, который использует загрузчик данных facebook под капотом - он не решит проблему того, какие поля запрашивать (хотя в примере используется knex, что значительно упростит задачу), но вместо этого он может кэшировать и группировать ваши запросы.

Другие вопросы по теме