Как получить выбранные поля в серверной части graphql с помощью функции распознавания типов graphql?

#node.js #typescript #graphql #typegraphql

#node.js #машинопись #graphql #typegraphql

Вопрос:

Я пишу распознаватель для извлечения данных из REST api в серверную функцию graphql с использованием typescript и type-graphql.Проблема, с которой я сталкиваюсь, заключается в том, что я получаю данные из API со всеми реквизитами, но я хочу возвращать только выбранные поля во внешнем интерфейсе. Как вернуть только выбранные поля?

Вот мой сценарий. У меня есть приложение react в качестве интерфейса. Я буду писать все запросы graphql в приложении fronetend. Во внешнем интерфейсе есть клиент apollo, который подключается к graphql в серверной части. Серверная часть — это приложение узла, написанное на машинописном языке. Мой серверный сервер извлекает данные из rest api и передает их во внешний интерфейс через сервер apollo. Мы используем type-graphql в серверной части

Здесь, в этом вопросе, у меня есть сомнения в отношении серверной части.

У меня есть следующий тип (определенный в серверной части как PersonInfo.ts)

 import { ObjectType, Field } from "type-graphql";

@ObjectType("PersonInfo")
export class PersonInfo {
  @Field({ nullable: true }) firstName: string;
  @Field({ nullable: true }) lastName: string;
  @Field({ nullable: true }) registrationNo: string;
  @Field({ nullable: true }) personCode: string;
  @Field({ nullable: true }) personCapabilities: string;
}
  

Я использую указанный выше тип в своем преобразователе, как показано ниже: (определено в серверной части как personInfoResolver.ts) Этот преобразователь graphql будет извлекать данные из rest api с помощью функции, написанной в следующей части. Эта функция имеет проблему, как указано в коде ниже.

 import { Query, Resolver, Arg } from "type-graphql";
import { PersonInfo } from "../types";
import { GetPersonInfo } from "./api/helpers";

@Resolver((of) => PersonInfo)
export class PersonInfoResolver {
  @Query((returns) => PersonInfo, { nullable: true })
  async PersonInfo(@Arg("serialNo") serialNo: string) {
    console.log(await GetPersonInfo(serialNo)); //<--this logs full object received from api with all the fields
    return await GetPersonInfo(serialNo); //when queried from graphql playground, i get null for selected values even if previous line prints all data
  }
}
  

Вот функция для получения данных в помощнике api (определенная в бэкэнде для подключения к api и получения данных.) Работает нормально и получает все объекты из rest api.

 export const GetPersonInfo = async (serialNo: string) => {
  var personInfoURL = "url"   serialNo;
  if (!serialNo) {
    return "";
  }
  const response = await posApi
    .get(personInfoURL)
    .then(function (response) {
      return response.data;
    })
    .catch(function (error) {});

  const data = await response;

  return data;
};
  

Я тестирую приведенный выше код с использованием graphql playground, используя следующий запрос.

   {
    PersonInfo(serialNo:"201123030"){
     firstName
     lastName
     registrationNo
     registrationNo
     personCapabilities

 }
}
  

Комментарии:

1. Этот вопрос неполный, где ваш graphql-запрос / мутация?

2. Или это то, что вам интересно? Как написать graphql-schema-функции?

3. Запрос @Joel будет находиться во внешнем интерфейсе приложения react. Прямо сейчас я пишу серверную часть в node и тестирую с использованием graphql play ground. Добавлен запрос, о котором идет речь

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

5. У вас была возможность взглянуть на мое решение?

Ответ №1:

Ваш вопрос мне неясен, но я постараюсь вам помочь.

Прежде всего, предоставленная вами схема GraphQL недействительна.

На игровой площадке вы должны написать:

 {
    PersonInfo(serialNo: "201123030") { //not DetailsInfo
        firstName
        ...
    }

}
  

Учитывая, что ваша сущность выглядит следующим образом:

 @Column()
@Field({ nullable: true }) firstName: string;
@Column()
@Field({ nullable: true }) lastName: string;
@Column()
@Field({ nullable: true }) registrationNo: string;
@Column()
@Field({ nullable: true }) personCode: string;
@Column()
@Field({ nullable: true }) personCapabilities: string;
  

И что ваш распознаватель выглядит так:

 @Resolver(PersonInfo)
export class PersonInfoResolver {
  @Query(() => PersonInfo, { nullable: true })
  async PersonInfo(@Arg("serialNo") serialNo: string): Promise<PersonInfo> {
    return await GetPersonInfo(serialNo); //when queried from graphql playground, i get null for selected values even if previous line prints all data
  }
}
  

Я рекомендую запустить

 npm i -D @graphql-codegen @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/operations @graphql-codegen/typescript-react-apollo
  

что позволяет автоматически генерировать схемы и обеспечивать безопасность типов в вашем проекте.

Создайте файл, вызываемый codegen.yml в вашем корневом каталоге вашего react-проекта (в том же месте, package.json что и)

 overwrite: true
schema: "http://localhost:4000/graphql"
documents: "src/graphql/**/*.graphql"
generates:
  src/generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
  

Создайте папку generated src/* в.

ИЛИ измените структуру выше на то, где вы хотите, чтобы схемы были сгенерированы.

Сначала вам нужно создать personinfo.query.graphql в src/graphql/queries/*

(Вы также можете создать другую папку, вызываемую src/graphql/mutations/ здесь)

personinfo.query.graphql

 query PersonInfo($serialNo: String!) { 
     personInfo(serialNo: $serialNo) {
         firstName,
         lastName,
         registrationNo,
         personCode,
         personCapabilities  //or whatever subset of fields you want.
     }
}
  

В вашей консоли введите: graphql-codegen --config codegen.yml и файлы будут сгенерированы. Откройте graphql.tsx сейчас и посмотрите, что он создал. Довольно аккуратно, не так ли?

Затем в вашем реагирующем компоненте просто сделайте:

 export const MyComponent: React.FC<{}> = ({}) => {

    const [{data}] = usePersonInfoQuery({/*your serialNo here*/}); //this function will have been generated now
    //then you have access to the fields you supplied to `personinfo.query.graphql`
    const fName = data.personInfo.firstName;
    const lName = data.personInfo.lastName;

}
  

Комментарии:

1. detailsinfo — это просто ошибка копирования вставки. Это было ранее detailsinfo. Обновлено в вопросе. Также добавлена дополнительная информация о контексте.

2. @GauravChauhan Пожалуйста, проверьте мое решение, оно показывает вам, как выбрать подмножество полей в вашем интерфейсе с помощью apollo.