GraphQL dynamic query building

风流意气都作罢 提交于 2019-12-10 01:44:41

问题


I have a GraphQL server which is able to serve timeseries data for a specified source (for example, sensor data). An example query to fetch the data for a sensor might be:

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

In my frontend, I want to allow the user to select 1 or more sources and show a chart with a line for each one. It seems like this would be possible by using a query like this:

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

Most GraphQL tutorials seem to focus on static queries (e.g. where the only thing that is changing is the variables, but not the actual shape of the request) - but in my case I need the query itself to be dynamic (one timeseriesData request for each of my selected ids).

I have the following constraints:

  1. Modifying the server's schema is not an option (so I can't pass an array of IDs to the resolver, for example)
  2. My query is specified using a template string e.g. gql`...`
  3. I don't want to have to manually build up the query as a string, because that seems like a recipe for disaster and would mean that I lose all tooling benefits (e.g. autocomplete, syntax highlighting, linting)

The stack I'm using is:

  • Apollo client (specifically apollo-angular)
  • Angular
  • TypeScript
  • graphql-tag (for defining queries)

Ideally, what I want to do is have some way of merging two queries into one, so that I can define them as per the first example but then join them together in an abstraction layer so that I get a single query like the second example to be sent over the wire.

However I'm not sure how to achieve this because graphql-tag is parsing the query into an AST and I'm struggling to understand whether it's feasable to manipulate the query in this way.

What techniques are there for generating a dynamic query like this, where the shape of the query is not known upfront?


回答1:


I think you could use fragments for this! But you still have to write 2 "queries" in this case fragments.

First let's create a fragment for each timeSeries, please check your timeSeries query type, I'm going to refer to it as 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
      }
    }
  }
}

And then just stitch them up in the query:

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



回答2:


You can use fragment to define common fields, and variable bound @include(if: Boolean) and @skip(if: Boolean) directives on that fragment to get dynamic fields that are known at execution time.



来源:https://stackoverflow.com/questions/51322346/graphql-dynamic-query-building

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!