Как запросить все поля типа 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.
4 answers
К сожалению, то, что вы хотели бы сделать, невозможно. GraphQL требует, чтобы вы четко указали, какие поля вы хотели бы получить из своего запроса.
Да, вы можете сделать это с помощью самоанализа . Сделайте запрос 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 использует самоанализ для создания типов.
Я думаю, что единственный способ сделать это - использовать повторно используемые фрагменты:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
Я столкнулся с той же проблемой, когда мне нужно было загрузить данные о местоположении, которые я сериализовал в базу данных из 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 в более общем плане.