简体   繁体   中英

Designing a GraphQL schema for an analytics platform

I'm just starting to explorer GraphQL as an option for my analytic platform API layer.

My UI is mainly built from tables and charts. most of the times the data represents some DB columns grouped by a dimension.

I've found the following article https://www.microsoft.com/developerblog/2017/09/28/data-independent-graphql-using-view-model-based-schemas/ from Microsoft, describing their take on how suck GraphQL schemas should be designed (see below).

type Query {
  channels(source: String!, query:String!, appId:String!, apiKey:String!): [Channel]
  lineCharts(source: String!, query:String!, appId:String!, apiKey:String!, filterKey:String, filterValues:[String]): [LineChart]
  pieCharts(source: String!, query:String!, appId:String!, apiKey:String!): [PieChart]
  barCharts(source: String!, query:String!, appId:String!, apiKey:String!, filterKey:String, filterValues:[String]): [BarChart]
}

type Channel {
  name: String
  id: Int
}

type LineChart {
  id: String
  seriesData : [Series]
}

type PieChart {
  id: String
  labels: [String]
  values: [Int]
}

type BarChart {
  id: String
  seriesData : [Series]
}

type Series {
  label: String
  x_values: [String]
  y_values: [Int]
}

It seems to me that this design is strict, forcing any new chart to be added to the root Query. How can the schema be more generic, without loosing GraphQL benefits?

You could do something with union types and inline/fragments

union Chart = LineChart | PieChart | BarChart

type Query {
  charts(
    source: String!
    query: String!
    appId: String!
    apiKey: String!
    filterKey: String
    filterValues: [String]
  ): [Chart]
}

Then you can have your charts resolver bring ALL the charts and write your queries like

fragment Identifiers on Chart {
  __typename
  id
}
query {
  charts(...) {
    ...on LineChart {
      ...Identifiers
      seriesData
    }
    ...on PieChart {
      ...Identifiers
      labels
      values
    }
    ...on BarChart {
      ...Identifiers
      seriesData
    }
  }
}

The Identifiers will provide you with some information about what type you're dealing with and it's id , but you can extend it to whatever you like as long as those fields are common to all types on that union (or you can spread it only on some of the types).

There are 2 ways you can go about if you don't want to bring in all the charts:

  1. Add inline fragments for only the types you want, but the rest will still be there, in the form of empty objects.
  2. Pass another argument to the resolver representing the type/s you want

PS You can get as granular as you like, there are also interfaces and input types .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM