Assume you have a GraphQL type and it includes many fields.
How to query all the fields without writing down a long query that includes the names of all the fields?
For example, If I have these fields :
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'
]
];
}
To query all the fields usually the query is something like this:
FetchUsers{users(id:"2"){id,username,count}}
But I want a way to have the same results without writing all the fields, something like this:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Is there a way to do this in GraphQL ??
I’m using Folkloreatelier/laravel-graphql library.
8
6 Answers
Reset to default
Unfortunately what you’d like to do is not possible. GraphQL requires you to be explicit about specifying which fields you would like returned from your query.
8
-
14
Ok, and if I request some object of an unknown form from backend which I’m supposed to proxy or send back?
– meandreNov 30, 2016 at 6:25
-
50
@meandre, the whole idea of graphql is that there is no such thing as an “unkown form”.
– s.meijerDec 28, 2016 at 22:16
-
3
@meandre, My answer below could be of use to you?
– Tyrone WilsonJan 15, 2017 at 12:54
-
2
interesting, it really is a different mindset when using graphql
– andy mcculloughMar 21, 2020 at 17:13
-
5
@s.meijer That’s all very nice on paper. Except that in the real world, devs just request the entire thing and looking at the keys and values quickly get an idea of what’s possible and what isn’t. GraphQL requires much more careful consideration of the documentation in this way, sometimes for things that are relatively benign. Also very annoying is that if you need all or most properties, you still have to enumerate them all just to retrieve the info. It seems like inspiration taken from SQL but important parts left out. Consider
SELECT *
– arossDec 29, 2021 at 18:29
Yes, you can do this using introspection. Make a GraphQL query like (for type UserType)
{
__type(name:"UserType") {
fields {
name
description
}
}
}
and you’ll get a response like (actual field names will depend on your actual schema/type definition)
{
"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. ...)
]
}
}
}
You can then read this list of fields in your client and dynamically build a second GraphQL query to get the values of all of these fields.
This relies on you knowing the name of the type that you want to get the fields for — if you don’t know the type, you could get all the types and fields together using introspection like
{
__schema {
types {
name
fields {
name
description
}
}
}
}
NOTE: this is the over-the-wire GraphQL data — you’re on your own to figure out how to read and write with your actual client. Your graphQL javascript library may already employ introspection in some capacity, for example the apollo codegen command uses introspection to generate types.
20222 Update
Since this answer was originally written, it is now a recommended security practice to TURN OFF introspection in production. Reference: Why you should disable graphql introspection in production.
For an environment where introspection is off in production, you could use it in development as a way to assist in creating a static query that was used in production; you wouldn’t actually be able to create a query dynamically in production.
8
-
Seems like one should express care about recursive types. If you went down the tree and bumped on to a type which contains itself, in some form (list, single or other..), you could be in for an infinite recursion.
– Milos GrujicMay 9, 2019 at 13:38
-
1
That doesn’t actually happen in my experience with this particular query — the query itself defines the resolution depth.
– Mark ChackerianMay 9, 2019 at 17:43
-
2
The above answer only allows you the query the types of fields available in a query. It doesn’t return all the object fields “values”, which is what the original question is about.
– quantdaddyAug 20, 2019 at 21:34
-
7
As per the answer, you have to dynamically build a second query based on the results of the first query — I left that as an exercise for the reader.
– Mark ChackerianAug 21, 2019 at 14:48
-
And the user that will do the exercise will discover the type UserType has a property fields which is an array of objects containing name and description properties – which he already knew since that’s exactly what he asked in his former query.
– Gin QuinJun 10, 2021 at 11:08
I guess the only way to do this is by utilizing reusable fragments:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
6
-
28
If I did that, then still I have to write each field name “at least in the fragment”, witch what I was trying to avoid, it seems that GraphQL force us to be explicit.
– BlackSigmaDec 15, 2015 at 12:53
-
how to add this in a POSTMan query? or jquery/UI framwork to make a stringified JSON . This graphiQL seems useless for actual development purpose.
– mfaisalhyderMay 15, 2019 at 5:07
-
This is solely for reuse purpose.
– Henok TesfayeMay 30, 2019 at 11:36
-
@BlackSigma Considering GraphQL documentation, this should be the accepted as best answer
– JP VenturaOct 13, 2019 at 9:35
-
8
@JPVentura: No my friend, there is a difference between reusability and wildcard both in concept and application. The fragment purpose is clear in the documentation ” GraphQL includes reusable units called fragments.” Using fragment is useful, but is not the answer for the question.
– BlackSigmaOct 31, 2019 at 23:27
I faced this same issue when I needed to load location data that I had serialized into the database from the google places API. Generally I would want the whole thing so it works with maps but I didn’t want to have to specify all of the fields every time.
I was working in Ruby so I can’t give you the PHP implementation but the principle should be the same.
I defined a custom scalar type called JSON which just returns a literal JSON object.
The ruby implementation was like so (using graphql-ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Then I used it for our objects like so
field :location, Types::JsonType
I would use this very sparingly though, using it only where you know you always need the whole JSON object (as I did in my case). Otherwise it is defeating the object of GraphQL more generally speaking.
5
-
3
This is exactly what I needed, thank you. My use case is I have user-translatable strings throughout the system, and they are stored as json in the db like
{"en": "Hello", "es": "Hola"}
. And since each user can implement their own subset of languages for their use case, it doesn’t make sense for the UI to query every possible subset. Your example works perfectly.– Luke EhresmanFeb 28, 2018 at 21:16
-
Otherwise it is defeating the object of GraphQL more generally speaking.
Who cares?– arossDec 29, 2021 at 18:32
-
1
I don’t understand enough Ruby to understand what exactly you did, but I assume you wrote code to represent the foreign object, and then just send an enumeration of its properties over the line? In any case, +1
– arossDec 29, 2021 at 18:34
-
@aross basically this is a straight pass through of a hashmap. in Typescript it would be
any
orunknown
, in golang it would bemap[string]interface{}
regardless, you are defining a custom type which just passes through whatever it receives. WRT your previous comment. Anyone who is trying to use GraphQL to shape and limit data over the wire, provide security for certain attributes or provide a Typesafe API. That’s who.– Tyrone WilsonJan 3, 2022 at 12:16
-
This is a global change, right? It seems like a more local change (i.e. specific to one model’s schema) could be to add a field (perhaps fields, columns, or whatever name would be more meaningful) and write a resolver that returns a json representation of all of the schema’s fields. Then, the query only has to return fields. And, other developers on your team will be clued in to the unique need for that model’s schema to have that representation.
– Boom100100May 16, 2022 at 15:38
GraphQL query format was designed in order to allow:
- Both query and result shape be exactly the same.
- The server knows exactly the requested fields, thus the client downloads only essential data.
However, according to GraphQL documentation, you may create fragments in order to make selection sets more reusable:
# Only most used selection properties
fragment UserDetails on User {
id,
username
}
Then you could query all user details by:
FetchUsers {
users() {
...UserDetails
}
}
You can also add additional fields alongside your fragment:
FetchUserById($id: ID!) {
users(id: $id) {
...UserDetails
count
}
}
Package graphql-type-json supports custom-scalars type JSON.
Use it can show all the field of your json objects.
Here is the link of the example in ApolloGraphql Server.
https://www.apollographql.com/docs/apollo-server/schema/scalars-enums/#custom-scalars
1
-
1
This question is about
php
and notnode.js
– zoran404Sep 15, 2022 at 13:26
Not the answer you’re looking for? Browse other questions tagged
or ask your own question.
or ask your own question.
You’re asking how to do something that GraphQL, by design, does not support.
Oct 25, 2016 at 2:28
It makes sense that it isnt supported, imagine you have Student and Class objects, student have field “classes” that lists all the classes he attends, class has field “students” that lists all students that attends that class. Thats a cyclical structure. Now if you request for all students with all fields, would that also include all fields of classes returned? And those classes has students, would their fields be included too? And students have classes, …
Apr 6, 2019 at 17:20
I had this question and it was so that I could see what was even available to pull. Lots of GraphQL clients (e.g. GraphiQL, see gatsbyjs.org/docs/running-queries-with-graphiql) have a schema explorer that uses the introspection to present you with what you can pull, if that’s the reason behind wanting to get “everything”.
Aug 3, 2020 at 20:53
Here is the discussion: github.com/graphql/graphql-spec/issues/127
Mar 3, 2021 at 14:15
I’m sorry, can I just say GraphQL sucks? I can get all the data in 1 request instead of 2… yay…! Give me the equivalent of
SELECT *
and I’ll reconsider… I’m not interested in saving 20 bytes by leaving out an email address field either.Jan 4, 2022 at 16:46
|
Show 3 more comments