1. ホーム
  2. javascript

[解決済み] GraphQLのネストされたクエリの定義

2022-03-06 06:33:42

質問

以下のようなクエリを排除するために、クエリにツリー状の構造を作ろうとしています。

peopleList, peopleSingle, peopleEdit, peopleAdd, peopleDelete companyList, companySingle, companyEdit, companyAdd, companyDelete etc. 

最終的には、このようなクエリを送信したいと思います。

query test {
  people {
    list {
      id
      name
    }
    single(id: 123) {
      id
      name
    }
  }
  company {
    list {
      id
      name
    }
    single(id: 456) {
      id
      name
    }
  }
}

mutation test2 {
  people {
    create(data: $var) {
      id
      name
    }
  }
  people {
    edit(id: 123, data: $var) {
      id
      name
    }
  }
}

これは、peopleモジュールのクエリオブジェクトの一部です。

people: {
  type: //What type this should be?
  name: 'Root of People queries',
  fields: () => ({
    list: {
      type: peopleType,
      description: 'Returns all people in DB.',
      resolve: () => {
        // resolve method implementation
      }
    },
    single: {
      type: peopleType,
      description: 'Single row from people table. Requires ID argument.',
      args: {
        id: { type: new GraphQLNonNull(GraphQLID) }
      },
      resolve: () => {
        // resolve method implementation
      }
    }
  })
}

このスニペットをGraphQLObjectTypeに入れ、RootQueryでそれらを結合しようとしましたが(GraphQLObjectTypeを再び使用)、うまくいきませんでした。

別の方法として、peopleQueriesTypeのような新しい型を作成し、この型の中ですべてのクエリをフィールドとして指定し、このオブジェクトのために単一のクエリを作成することができます。しかし、これでは、私のクエリをツリー状にマージするためだけに、不要なオブジェクトでコードを汚染することになり、奇妙な感じがします。

Apolloサーバーの実装で、このようなクエリ構造が可能かどうか調べてみましたが、ドキュメントには何も書かれていませんでした。

サーバーはnode.js + express + graphql-jsを使用しています。

どのように解決するのですか?

簡単にお答えします。
タイプは GraphQLObjectType このようにすべてのフィールドを含む。

type: new GraphQLObjectType({ name: 'patientQuery', fields: { find, findOne } })

詳細 結局、以下のようなコードでこのクエリにたどり着きました。

{
  patient {
    find {
      id
      active
    }
    findOne(id: "pat3") {
      id
      active
    }
  }
}

patient/queries/index.js 私はこれを

import findOne from './find-one.js';
import find from './find.js';
import { GraphQLObjectType } from 'graphql';

export default {
  patient: {
    type: new GraphQLObjectType({ name: 'patientQuery', fields: { find, findOne } }),
    resolve(root, params, context, ast) {
      return true;
    }
  }
};

であれば queries.js

import patient from './patient/queries/index.js';
export default {
  ...patient
};

そして最後に私のスキーマ schema.js グラフィー・エクスプレス・サーバーに渡される

import {
  GraphQLObjectType,
  GraphQLSchema
} from 'graphql';

import queries from './queries';
import mutations from './mutations';

export default new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: queries
  }),
  mutation: new GraphQLObjectType({
    name: 'Mutation',
    fields: mutations
  })
});