GraphQl и запросы API условного резольвера - PullRequest
0 голосов
/ 24 января 2020

Я не знал, как озаглавить этот вопрос, но вот в чем я не уверен.

У меня есть интерфейс React, который выполняет запрос GraphQl к нашему промежуточному слою GraphQl, который объединяет данные, делая вызовы к нашему legacy REST api.

Так, например, в React я могу вызвать запрос getCustomer:

query getCustomer($id: Int!) {
    getCustomer(id: $id) {
      name
      email
  }
}

, который попадет на распознаватель getCustomer, который затем отправит запрос нашему REST customers/{id} конечная точка для возврата наших данных.

async function getCustomer(_, { id }, ctx) {
  const customer = await ctx.models.customer.getCustomer(id);
  return customer;
}

Этот запрос подходит, если я печатаю список клиентов. Но где мои вопросы вступают в игру, как я могу сделать условные запросы API в моем преобразователе на основе данных, которые я запрашиваю?

Скажем, у каждого клиента может быть несколько адресов, и эти адреса живут на разных конечных точках. Я хотел бы получить эти адреса, как это в моем интерфейсе:

query getCustomer($id: Int!) {
    getCustomer(id: $id) {
      name
      email
      address {
        city
      }
  }
}

Как я могу сделать так, чтобы мой распознаватель обрабатывал это на основе моих types и schemas? Что-то вроде этого:

async function getCustomer(_, { id }, ctx) {
  const customer = await ctx.models.customer.getCustomer(id);

  [If the query includes the address field]
    const addresses = await ctx.models.customer.getAddressesByCustomer(id);
    customer.addresses = addresses;
  [/If]

  return customer;
}

В конечном итоге цель состоит в том, чтобы преобразователь getCustomer мог возвращать все данные клиента через различные конечные точки в зависимости от того, какие поля отправлены в запросить, но не делать эти дополнительные запросы API, если поле не запрошено.

Ответы [ 3 ]

1 голос
/ 24 января 2020

Есть два способа сделать это. Первый основан на том, как GraphQL выполняет запросы. Средство распознавания поля будет вызываться только в том случае, если 1) поле «родитель» не равно нулю и 2) поле действительно запрашивается. Это означает, что мы можем предоставить резольвер для поля адреса в явном виде:

const resolvers = {
  Customer: {
    addresses: () => {
      return ctx.models.customer.getAddressesByCustomer(id)
    },
  },
}

Таким образом, резолвер будет вызываться для запроса, подобного

{
  query getCustomer($id: Int!) {
    getCustomer(id: $id) {
      name
      address {
        city
      }
    }
  }
}

, но не будет будет вызываться для

{
  query getCustomer($id: Int!) {
    getCustomer(id: $id) {
      name
    }
  }
}

Этот подход достаточно хорошо работает при переносе простого REST API. Однако некоторые REST API позволяют запрашивать связанные ресурсы через необязательные параметры. Аналогично, если вы извлекаете данные из базы данных, вы можете присоединить дополнительные таблицы к вашему запросу. Конечный результат - больше данных за меньшее количество циклов. В этом случае вы должны выполнить все выборки на уровне root (внутри резольвера getCustomer). Однако вы бы хотели определить, какие поля на самом деле запрашивал пользовательский. Для этого вы должны проанализировать информационный объект разрешения , который является четвертым параметром, передаваемым каждому распознавателю. После того, как вы определили, какие поля были фактически запрошены, вы можете внести соответствующие изменения в свой URL или SQL запрос.

0 голосов
/ 24 января 2020

Ваши средства распознавания должны выглядеть следующим образом:

const resolvers = {
  Query: {
    getCustomer(id) {
      // return customer object
    }
  },
  Customer: {
    addresses(customer) {
      // return addresses of the customer
    }
  }
}

Сервер Graphql позаботится о вызове соответствующего преобразователя.

Если вы определяете свою схему прагматично, вы можете определить преобразователь вместе с определение поля.

0 голосов
/ 24 января 2020

Аполлон проверяет / знает, какие поля заполнены и что нужно запрашивать дополнительно. Он вызывает один (основной, верхний уровень) распознаватель (для возврата имени и электронной почты) и вызывает дополнительные распознаватели, когда возвращаемый объект не содержит требуемых данных (поле / дочерние / связанные).

Быстрый обходной путь : используйте [мощность] ctx info параметр, чтобы проверить, какие поля были обязательны для заполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...