Подтвердить что ты не робот

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

4b9b3361

Ответ 1

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

Ответ 2

Да, вы можете сделать это, используя самоанализ. Сделайте запрос 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 использует интроспекцию для генерации типов.

Ответ 3

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

fragment UserFragment on Users {
    id
    username
    count
} 

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

Ответ 4

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

Я работал в 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.

Ответ 5

Формат запроса GraphQL разработан для того, чтобы:

  1. Форма запроса и результата будет абсолютно одинаковой.
  2. Сервер знает точно запрошенные поля, поэтому клиент загружает только важные данные.

Однако, согласно документации GraphQL, вы можете создавать фрагменты, чтобы сделать наборы выбора более пригодными для повторного использования:

# Only most used selection properties

fragment UserDetails on User {
    id,
    username
} 

Затем вы можете запросить все данные пользователя:

FetchUsers {
    users() {
        ...UserDetails
    }
}

Вы также можете добавить дополнительные поля рядом с вашим фрагментом:

FetchUserById($id: ID!) {
    users(id: $id) {
        ...UserDetails
        count
    }
}