How to query all the GraphQL type fields without writing a long query?

How to query all the GraphQL type fields without writing a long query?

316

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.

Share
Improve this question

8

  • 17

    You’re asking how to do something that GraphQL, by design, does not support.

    – Travis Webb

    Oct 25, 2016 at 2:28

  • 6

    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, …

    – Buksy

    Apr 6, 2019 at 17:20

  • 4

    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”.

    – James

    Aug 3, 2020 at 20:53

  • 2

    Here is the discussion: github.com/graphql/graphql-spec/issues/127

    – Kris

    Mar 3, 2021 at 14:15

  • 5

    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.

    – aross

    Jan 4, 2022 at 16:46


6 Answers
6

Reset to default

304

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.

Share
Improve this answer

8

  • 14

    Ok, and if I request some object of an unknown form from backend which I’m supposed to proxy or send back?

    – meandre

    Nov 30, 2016 at 6:25

  • 50

    @meandre, the whole idea of graphql is that there is no such thing as an “unkown form”.

    – s.meijer

    Dec 28, 2016 at 22:16

  • 3

    @meandre, My answer below could be of use to you?

    – Tyrone Wilson

    Jan 15, 2017 at 12:54

  • 2

    interesting, it really is a different mindset when using graphql

    – andy mccullough

    Mar 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 *

    – aross

    Dec 29, 2021 at 18:29

207

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.

Share
Improve this answer

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 Grujic

    May 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 Chackerian

    May 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.

    – quantdaddy

    Aug 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 Chackerian

    Aug 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 Quin

    Jun 10, 2021 at 11:08

65

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
    }
}

Share
Improve this answer

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.

    – BlackSigma

    Dec 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.

    – mfaisalhyder

    May 15, 2019 at 5:07

  • This is solely for reuse purpose.

    – Henok Tesfaye

    May 30, 2019 at 11:36

  • @BlackSigma Considering GraphQL documentation, this should be the accepted as best answer

    – JP Ventura

    Oct 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.

    – BlackSigma

    Oct 31, 2019 at 23:27

17

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.

Share
Improve this answer

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 Ehresman

    Feb 28, 2018 at 21:16

  • Otherwise it is defeating the object of GraphQL more generally speaking. Who cares?

    – aross

    Dec 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

    – aross

    Dec 29, 2021 at 18:34

  • @aross basically this is a straight pass through of a hashmap. in Typescript it would be any or unknown, in golang it would be map[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 Wilson

    Jan 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.

    – Boom100100

    May 16, 2022 at 15:38

6

GraphQL query format was designed in order to allow:

  1. Both query and result shape be exactly the same.
  2. 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
    }
}

Share
Improve this answer

    1

    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

    Share
    Improve this answer

    1

    • 1

      This question is about php and not node.js

      – zoran404

      Sep 15, 2022 at 13:26



    Your Answer


    Post as a guest

    Required, but never shown


    By clicking тАЬPost Your AnswerтАЭ, you agree to our terms of service, privacy policy and cookie policy

    Not the answer you’re looking for? Browse other questions tagged

    or ask your own question.

    Leave a Reply

    Your email address will not be published. Required fields are marked *