web-dev-qa-db-ja.com

長いクエリを作成せずに、すべてのGraphQLタイプのフィールドをクエリする方法は?

GraphQLタイプがあり、多くのフィールドが含まれているとします。すべてのフィールドの名前を含む長いクエリを書き留めずに、すべてのフィールドをクエリする方法は?

たとえば、これらのフィールドがある場合:

 public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the user'
            ],
            'username' => [
                'type' => Type::string(),
                'description' => 'The email of user'
            ], 
             'count' => [
                'type' => Type::int(),
                'description' => 'login count for the user'
            ]

        ];
    }

通常、すべてのフィールドをクエリするには、クエリは次のようになります。

FetchUsers{users(id:"2"){id,username,count}}

しかし、次のようなすべてのフィールドを記述せずに同じ結果を得る方法が必要です。

FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}

GraphQLでこれを行う方法はありますか?

Folkloreatelier/laravel-graphqlライブラリを使用しています。

83
BlackSigma

残念ながら、やりたいことはできません。 GraphQLでは、クエリから返されるフィールドを明示的に指定する必要があります。

65
Peter Horne

はい、あなたはcanintrospection を使用してこれを行うことができます。 (タイプUserTypeのような)GraphQLクエリを作成します

{
   __type(name:"UserType") {
      fields {
         name
         description
      }  
   }
}

次のような応答が返されます(実際のフィールド名は、実際のスキーマ/型定義に依存します)

{
  "data": {
    "__type": {
      "fields": [
        {
          "name": "id",
          "description": ""
        },
        {
          "name": "username",
          "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
        },
        {
          "name": "firstName",
          "description": ""
        },
        {
          "name": "lastName",
          "description": ""
        },
        {
         "name": "email",
          "description": ""
        },
        ( etc. etc. ...)
      ]
    }
  }
}

次に、クライアントでこのフィールドのリストを読み取り、2番目のGraphQLクエリを動的に構築して、これらのすべてのフィールドを取得できます。

これは、フィールドを取得するタイプの名前を知っていることを前提としています。タイプがわからない場合は、次のようなイントロスペクションを使用して、すべてのタイプとフィールドを一緒に取得できます。

{
  __schema {
    types {
      name
      fields {
        name
        description
      }
    }
  }
}

注:これは有線のGraphQLデータです。実際のクライアントで読み書きする方法を自分で考えてください。 graphQL javascriptライブラリは、ある程度のイントロスペクションを既に使用している場合があります。たとえば、 apollo codegen コマンドは、イントロスペクションを使用して型を生成します。

57
Mark Chackerian

これを行う唯一の方法は、再利用可能なフラグメントを利用することです。

fragment UserFragment on Users {
    id
    username
    count
} 

FetchUsers {
    users(id: "2") {
        ...UserFragment
    }
}
26
tommy

Google Places APIからデータベースにシリアル化した位置データを読み込む必要があるときに、この同じ問題に直面しました。一般に、マップ全体で機能するようにしたいのですが、毎回すべてのフィールドを指定する必要はありませんでした。

私はRubyで働いていたので、PHP実装を提供することはできませんが、原則は同じでなければなりません。

リテラルJSONオブジェクトを返すだけのJSONというカスタムスカラー型を定義しました。

Ruby実装はそのようでした(graphql-Rubyを使用)

module Graph
  module Types
    JsonType = GraphQL::ScalarType.define do
      name "JSON"
      coerce_input -> (x) { x }
      coerce_result -> (x) { x }
    end
  end
end

それから私はそれをオブジェクトに使用しました

field :location, Types::JsonType

私はこれを非常に控えめに使用しますが、JSONオブジェクト全体が常に必要であることがわかっている場合にのみ使用します(私の場合のように)。それ以外の場合、より一般的に言えば、GraphQLのオブジェクトを無効にします。

7
Tyrone Wilson