引数に基づく動的フィールドを持つ GraphQL ObjectType 質問する

引数に基づく動的フィールドを持つ GraphQL ObjectType 質問する

GraphQL クエリの応答では、オブジェクトのいくつかの動的プロパティを返す必要があります。この場合、すべての可能なプロパティを事前に定義することはできないため、動的にする必要があります。

これを解決するには 2 つの選択肢があると考えます。

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      /*
      THIS is our special field which needs to return a dynamic object 
      */
    },
    // ...
  },
});

サンプル コードでわかるように、要素はオブジェクトを返すプロパティです。これを解決した場合の応答は次のようになります。

{
  name: 'some name',
  elements: {
    an_unkonwn_key: {
      some_nested_field: {
        some_other: true,
      },
    },
    another_unknown_prop: 'foo',
  },
}

1) 「Any-Object」を返す

任意のオブジェクトを返すだけでよいので、GraphQL はオブジェクトがどのフィールドを持っているかを知る必要がありません。GraphQL にフィールドが GraphQlObjectType 型であることを伝える場合、フィールドを定義する必要があります。このため、GraphQL に誰かが単なるオブジェクトであることを伝えることはできないようです。

このため、次のように変更しました。

elements: {
      type: new GraphQLObjectType({ name: 'elements' });
    },

2) 関数内にあるため、動的なフィールドプロパティを定義できる。

フィールドを関数として定義すると、オブジェクトを動的に定義できます。ただし、フィールド関数には何らかの情報 (この場合は要素に渡される情報) が必要になり、フィールド オブジェクトを構築するにはそれらの情報にアクセスする必要があります。

例:

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      type: new GraphQLObjectType({
        name: 'elements',
        fields: (argsFromElements) => {
          // here we can now access keys from "args"
          const fields = {};
          argsFromElements.keys.forEach((key) => {
            // some logic here ..
            fields[someGeneratedProperty] = someGeneratedGraphQLType;
          });
          return fields;
        },
      }),
      args: {
        keys: {
          type: new GraphQLList(GraphQLString),
        },
      },
    },
    // ...
  },
});

これは機能する可能性がありますが、引数を渡したり、オブジェクトをフィールドに解決したりする方法があるかどうかが疑問になります。

質問そこで、今の質問は次のようになります。GraphQL の場合、どちらの方法が推奨されるのでしょうか。解決策 1 または 2 は可能ですか? 別の解決策があるのでしょうか?

編集ソリューション 1 は、ScalarType を使用する場合に機能します。例:

type: new GraphQLScalarType({
        name: 'elements',
        serialize(value) {
          return value;
        },
      }),

これが私たちの状況を解決するための推奨される方法であるかどうかはわかりません。

ベストアンサー1

どちらの選択肢も実際には実行可能ではありません。

  1. GraphQL は厳密に型付けされています。GraphQL.js は一部のanyフィールドをサポートしておらず、スキーマで定義されているすべての型にはフィールドが定義されている必要があります。ドキュメントを見るとfields必須です。省略するとエラーが発生します。

  2. 引数はリクエストごとにクエリを解決するために使用されます。それらをスキーマに戻すことはできません。スキーマは静的である必要があります。

あなたが提案したように、独自の顧客スカラーを作成することで、あなたがしようとしていることを実現することは可能です。より簡単な解決策は、JSONを使用することだと思います。このようなカスタムスカラー次に、elementsフィールドを動的フィールドを含む JSON オブジェクトまたは配列に解決します。必要に応じて、引数に基づいてリゾルバ内で JSON オブジェクトを操作することもできます (たとえば、返されるフィールドを引数で定義されたサブセットに制限する場合など)。

警告の言葉:JSONやネストされたデータを含むカスタムスカラーを利用する際の問題は、クライアントが実際に必要とするものを要求する際の柔軟性が制限されることです。また、クライアント側であまり役に立たないエラーが発生します。要求したフィールドが存在しない、またはnullが返されたという通知の方がずっとありがたいです。私がリクエストをするとき後になって、取得した JSON BLOB に期待していたフィールドが含まれていないことに気づくよりも、

おすすめ記事