Как запросить все поля типа 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??

Я использование библиотеки Фольклорист/laravel-graphql.

Author: falinsky, 2015-12-10

4 answers

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

 43
Author: Peter Horne, 2015-12-11 15:03:54

Да, вы можете сделать это с помощью самоанализа . Сделайте запрос GraphQL, подобный (для типа UserType)

{ __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. ...)
      ]
    }
  }
}

Затем вы можете прочитать этот список полей в своем клиенте и динамически построить второй запрос GraphQL, чтобы получить все эти поля.

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

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

ПРИМЕЧАНИЕ: это данные GraphQL по сети - вы сами должны выяснить, как читать и писать с вашим реальным клиентом. Ваша библиотека javascript GraphQL может уже использовать самоанализ в некотором качестве, например, команда apollo codegen использует самоанализ для создания типов.

 33
Author: Mark Chackerian, 2018-08-15 19:18:31

Я думаю, что единственный способ сделать это - использовать повторно используемые фрагменты:

fragment UserFragment on Users {
    id
    username
    count
} 

FetchUsers {
    users(id: "2") {
        ...UserFragment
    }
}
 22
Author: tommy, 2015-12-10 15:08:17

Я столкнулся с той же проблемой, когда мне нужно было загрузить данные о местоположении, которые я сериализовал в базу данных из API google places. Как правило, я хотел бы, чтобы все это работало с картами, но я не хотел каждый раз указывать все поля.

Я работал в Ruby, поэтому я не могу дать вам реализацию PHP, но принцип должен быть таким же.

Я определил пользовательский скалярный тип под названием JSON, который просто возвращает буквальный объект JSON.

Рубин реализация была такой (с использованием 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 в более общем плане.

 6
Author: Tyrone Wilson, 2017-01-15 12:52:16