Comment interroger tous les champs de type GraphQL sans écrire une longue requête?

Supposons que vous avez un type GraphQL et qu'il inclut de nombreux champs. Comment interroger tous les champs sans écrire une longue requête qui contient les noms de tous les champs?

Par exemple, Si j'ai ces champs :

 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'
            ]

        ];
    }

Pour interroger tous les champs, la requête ressemble généralement à ceci:

FetchUsers{users(id:"2"){id,username,count}}

Mais je veux un moyen d'avoir les mêmes résultats sans écrire tous les champs, quelque chose comme ceci:

FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}

Y a-t-il un moyen de le faire dans GraphQL??

Je suis en utilisant Folkloreatelier / laravel-graphql bibliothèque.

49
demandé sur falinsky 2015-12-10 13:50:43

4 réponses

Malheureusement, ce que vous aimeriez faire n'est pas possible. GraphQL exige que vous soyez explicite sur la spécification des champs que vous souhaitez renvoyer de votre requête.

43
répondu Peter Horne 2015-12-11 15:03:54

Oui, vous Pouvez le faire en utilisant introspection. Créez une requête GraphQL comme (pour le type UserType)

{ __type(name:"UserType") {
    fields {
      name
      description
      }  
    }
}

Et vous obtiendrez une réponse comme (les noms de champs réels dépendront de votre définition de schéma/type réelle)

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

Vous pouvez ensuite lire cette liste de champs dans votre client et construire dynamiquement une deuxième requête GraphQL pour obtenir tous ces champs.

Cela repose sur le fait que vous connaissez le nom du type pour lequel vous voulez obtenir les champs-si vous vous ne connaissez pas le type, vous pouvez obtenir tous les types et champs ensemble en utilisant l'introspection comme

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

NOTE: Ce sont les données GraphQL over-the-wire-vous êtes seul pour comprendre comment lire et écrire avec votre client réel. Votre bibliothèque javascript graphQL peut déjà utiliser l'introspection dans une certaine mesure, par exemple la commande Apollo codegen utilise l'introspection pour générer des types.

33
répondu Mark Chackerian 2018-08-15 19:18:31

Je suppose que la seule façon de le faire est d'utiliser réutilisables fragments:

fragment UserFragment on Users {
    id
    username
    count
} 

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

J'ai rencontré ce même problème lorsque j'ai eu besoin de charger des données de localisation que j'avais sérialisées dans la base de données à partir de l'API google places. En général, je voudrais que le tout fonctionne avec des cartes, mais je ne voulais pas avoir à spécifier tous les champs à chaque fois.

Je travaillais dans Ruby donc je ne peux pas vous donner L'implémentation PHP mais le principe devrait être le même.

J'ai défini un type scalaire personnalisé appelé JSON qui renvoie simplement un objet JSON littéral.

Le rubis l'implémentation était comme ça (en utilisant graphql-ruby)

module Graph
  module Types
    JsonType = GraphQL::ScalarType.define do
      name "JSON"
      coerce_input -> (x) { x }
      coerce_result -> (x) { x }
    end
  end
end

Ensuite, je l'ai utilisé pour nos objets comme ceci

field :location, Types::JsonType

Je l'utiliserais avec parcimonie, en l'utilisant uniquement lorsque vous savez que vous avez toujours besoin de l'objet JSON entier (comme je l'ai fait dans mon cas). Sinon, c'est vaincre L'objet de GraphQL plus généralement.

6
répondu Tyrone Wilson 2017-01-15 12:52:16