web-dev-qa-db-fra.com

Création de requêtes dynamiques GraphQL

J'ai un serveur GraphQL qui est capable de servir des données de série temporelle pour une source spécifiée (par exemple, des données de capteur). Un exemple de requête pour récupérer les données d'un capteur peut être:

query fetchData {
    timeseriesData(sourceId: "source1") {
      data {
        time
        value
      }
    }
}

Dans mon interface, je veux permettre à l'utilisateur de sélectionner une ou plusieurs sources et d'afficher un graphique avec une ligne pour chacune. Il semble que cela serait possible en utilisant une requête comme celle-ci:

query fetchData {
    series1: timeseriesData(sourceId: "source1") {
      data {
        time
        value
      }
    }
    series2: timeseriesData(sourceId: "source2") {
      data {
        time
        value
      }
    }
}

La plupart des didacticiels GraphQL semblent se concentrer sur les requêtes statiques (par exemple, où la seule chose qui change est les variables, mais pas la forme réelle de la demande) - mais dans mon cas, j'ai besoin de la requête elle-même pour être dynamique (une requête timeseriesData pour chacun de mes identifiants sélectionnés).

J'ai les contraintes suivantes:

  1. La modification du schéma du serveur n'est pas une option (je ne peux donc pas transmettre un tableau d'ID au résolveur, par exemple)
  2. Ma requête est spécifiée à l'aide d'une chaîne de modèle, par exemple gql` ... `
  3. Je ne veux pas avoir à créer manuellement la requête sous forme de chaîne, car cela semble être une recette pour un désastre et cela signifierait que je perdrais tous les avantages de l'outillage (par exemple, saisie semi-automatique, mise en évidence de la syntaxe, peluchage)

La pile que j'utilise est:

  • Client Apollo (spécifiquement apollo-angulaire)
  • Angular
  • Manuscrit
  • graphql-tag (pour définir les requêtes)

Idéalement, ce que je veux faire, c'est avoir un moyen de fusionner deux requêtes en une seule, afin que je puisse les définir comme dans le premier exemple, puis les réunir dans une couche d'abstraction afin d'obtenir une seule requête comme le deuxième exemple pour être envoyé sur le fil.

Cependant, je ne sais pas comment y parvenir, car graphql-tag analyse la requête en un AST et j'ai du mal à comprendre s'il est possible de manipuler la requête de cette manière.

Quelles techniques existe-t-il pour générer une requête dynamique comme celle-ci, où la forme de la requête n'est pas connue à l'avance?

9
Matt Wilson

Vous pouvez utiliser un fragment pour définir des champs communs et des directives @include(if: Boolean) et @skip(if: Boolean) liées aux variables sur ce fragment pour obtenir des champs dynamiques connus au moment de l'exécution.

2
SnnSnn

Je pense que vous pourriez utiliser fragments pour cela! Mais vous devez encore écrire 2 "queries" dans ce cas fragments.

Créons d'abord un fragment pour chaque timeSeries, veuillez vérifier votre type de requête timeSeries, je vais y faire référence comme timeseriesDataQuery

const series1Q = gql`
  fragment series1 on timeseriesDataQuery {
    series1: timeseriesData(sourceId: "source1") {
      data {
        time
        value
      }
    }
  }
}

const series2Q = gql`
  fragment series2 on timeseriesDataQuery {
    series2: timeseriesData(sourceId: "source2") {
      data {
        time
        value
      }
    }
  }
}

Et puis il suffit de les assembler dans la requête:

export const mainQuery = gql`
    query fetchData {
      ...series1 
      ...series2
    }
    ${series1Q}
    ${series2Q}
`    
2
Marco Daniel