6
votes

Graphql fusionne (combine) plusieurs requêtes en une seule?

J'essaie de combiner plusieurs requêtes Graphql en une seule requête à l'aide de JavaScript.
Je recherche quelque chose comme ceci:

{
  post(id: 1234) {
    title
    tags
    description
    author {
      name
    }
  }
}

Nous ne saurons pas à l'avance quelles requêtes seront combinées.

Supposons que j'ai des requêtes comme celle-ci:

input query1:

{
  post(id: 1234) {
    tags
    author {
      name
    }
  }
}

input query2:

{
  post(id: 1234) {
    title
    description
  }
}

Ensuite, je voudrais que le résultat query3 soit:
résultat query3:

let query3 = mergeQueries(query1, query2);

Ce serait la même fonctionnalité que lodash _.merge () fait pour les objets JSON, mais avec des requêtes Graphql au lieu de Objets JSON.


2 commentaires

essayez-vous de minimiser le nombre de requêtes HTTP? si oui, cela pourrait aider blog.apollographql.com/query-batching-in-apollo -63acfd859862


Vous ne pouvez pas faire cela par une simple manipulation textuelle; vous devez analyser les requêtes GraphQL et les joindre. Cela peut se compliquer en présence de correspondance de type dynamique et de fragments.


3 Réponses :


7
votes

Ma réponse devient un peu trop longue pour un commentaire, j'ai donc décidé d'écrire une réponse directe ici. Premièrement, je pense que les deux commentaires sont vraiment utiles. Il existe une solution qui permet à deux requêtes de partager une requête HTTP qui pourrait déjà être l'optimisation que vous recherchez. De plus, la fusion des requêtes n'est pas anodine. Cela demande beaucoup d'efforts pour le faire au niveau du terrain. Non seulement les fragments peuvent rendre cela difficile, mais vous devez également prendre en compte des variables. Autant que je sache, il n'y a pas de solution accessible au public pour le faire, vous devrez donc le faire vous-même. Je n'ai pas non plus entendu parler d'une entreprise qui fait cela. Je pense que le fait qu'il n'y ait pas de solution est un indicateur que cela ne vaut peut-être pas la peine de le faire.

Je ne peux que deviner votre problème, mais une autre façon de réduire le nombre de requêtes envoyées par une application frontale est de utiliser des fragments. Bien que vos fragments ne puissent pas avoir de variables, une structure de composant saine s'adaptera toujours très bien aux fragments:

fragment PostHeader on Post {
  title
  description
}

fragment PostMeta on Post {
  tags
  author {
    name
  }
}

query {
  post(id: 1234) {
    ...PostHeader
    ...PostMeta
  }
}


2 commentaires

Cela ressemble à une solution très utile dans de nombreux cas. Je m'attends à beaucoup de chevauchement entre les requêtes d'entrée, ce qui rendra cette solution moins idéale, je vais donc envisager de créer ma propre fonction de fusion.


Nous avons écrit du code pour combiner des fragments, avec un nom automatique des fragments et la suppression des fragments en double, et l'avons publié ici: github.com/SVT/graphql-defragmentizer



2
votes

Grâce aux fragments paramétrés, vous pouvez prendre en compte des variables! En supposant que post est un champ du type de requête racine, la requête combinée faisant référence à l'exemple ci-dessus serait:

fragment PostHeader on RootQueryType {
  post(id: $id) {
    tags
    author {
      name
    }
  }
}

fragment PostMeta on RootQueryType {
  post(id: $id) {
    tags
    author {
      name
    }
  }
}

# ID being the id type
query(id: ID! = 1234) {
  ...PostHeader
  ...PostMeta
}

ou plutôt dans un scénario réel, vous passer l'identifiant de manière dynamique (par exemple dans votre demande de publication), voir: https://graphql.org / learn / queries / # variables


0 commentaires

-1
votes

J'ai écrit une bibliothèque pour ceci: https://github.com/domasx2/graphql- combinaison-requête

import comineQuery from 'graphql-combine-query'

import gql from 'graphql-tag'

const fooQuery = gql`
  query FooQuery($foo: String!) {
    getFoo(foo: $foo)
  }
`

const barQuery = gql`
  query BarQuery($bar: String!) {
    getBar(bar: $bar)
  }
`

const { document, variables } = combineQuery('FooBarQuery')
  .add(fooQuery, { foo: 'some value' })
  .add(barQuery, { bar: 'another value' })

console.log(variables)
// { foo: 'some value', bar: 'another value' }

print(document)
/*
query FooBarQuery($foo: String!, $bar: String!) {
   getFoo(foo: $foo)
   getBar(bar: $bar)
}
*/


2 commentaires

Cela semblait encourageant, mais c'est vraiment frais et comporte des bugs. Le nom du package est mal orthographié dans package.json.


@ivanjonas, quel était le bogue, à part le nom du paquet?