31

I'm am very interested by GraphQL for an analytic solution (think of an webapp displaying graphs). But I cannot find any examples of GraphQL using aggregate function. This is a main aspect of most of the queries done by my frontend.

For my solution, we have 3 typical backend calls.

  1. Search
  2. Aggregate
  3. Time Series

Let say we have this type specified in GraphQL

type Person {
  name: String
  age: Int
  create_time: Date
}
  1. Search

This seems to be well handled by GraphQL. No question here.

ex. Search age of Person named Bob { Person(name: "Bob") { age } }

  1. Aggregate

This is the typical case where I want to display the info in a Pie Chart. So let say I want to count the number of person by age.

Here would be the PostgreSQL query:

SELECT age, count(*) from Ticket group by age;

What would be the equivalent in GraphQL?

  1. Time Series This is the typical case where I want to display the info in a BarChart with the X axis as time.

ex. Let say I want to count the number of created user per hour.

Here would be the PostgreSQL query:

SELECT date_trunc('hour', create_time) as create_time_bin, count(*) from Person group by create_time_bin order by create_time_bin ASC;

What would be the GraphQL equivalent query?

Damien
  • 1,944
  • 2
  • 18
  • 21
  • 1
    Not to mention, how do you do range comparisons for scalars, like SELECT * WHERE timestamp > … AND timestamp < …? Or sorting of results by a scalar? I don’t see any of these in the spec. What am I missing? – Justin Makeig Jan 27 '16 at 20:18
  • You add parameters to your fields that allow for that type of filtering. – Ryan Jan 29 '16 at 00:28

3 Answers3

17

GraphQL, at the end of the day, responds with your defined types. You just need to put that data into a type. Whether this is a specific type for these different queries, or fields for that data on existing types, it's up to you but that's all it boils down to. GraphQL does require more effort up front in terms of defining your types and what all queries will return, which makes it more rigid, but the idea is that on other side of that lies some cool features, like introspection and type checking. If it doesn't seem to make logical sense to put that sort of "ad hoc" data structures into a GraphQL type, then it's not illegal to have non-GraphQL endpoints if you need other data sources.

Ryan
  • 7,733
  • 10
  • 61
  • 106
  • I think I get what you are saying, but I get how the implementation of this would look like. – Damien Feb 03 '16 at 14:18
  • 7
    @Damien, every GraphQL query is responded to by a resolve() function. The query parameters you give to the query are the arguments to this function. The resolve() function then goes away and does anything you want, say retrieve the results of a SQL query from elsewhere, then you can aggregate that data as you like, and finally return the outcome of all that as your response to the GraphQL query. Point being: You're supposed to do the aggregation as if resolve() was just another JS function returning numbers. But the querying client doesn't need to know or care. – batjko Apr 13 '16 at 15:19
15

@Damien, those problems are not GraphQL's problems.

Whenever you want do something in GraphQL you must define a Type of return data, Spec of function you implement, and sometimes a Type of input data to feed into your function. Finally you write code to do the job.

In fact, it looks like you (re)write your code in GraphQL language.

Take the example where you want to display the info in a Pie Chart:

SELECT age, count(*) from Ticket group by age;

Define your return data here is a list of age and count:

 type TickGroupByAge {
      age: Int
      count: Int
    }

Define your function or Query in GraphQL language:

getTicketGroupByAge : [TickGroupByAge]`

Finally write a function to implement above query:

async function(){
    const res = await client.query("SELECT age, count(*) from Ticket group by age");
    return res.rows;
}

@Ryan I totally agree with you that GraphQL forces you to write a lot of type definitions to resolve a simple task. For that reason, I ended up building my own NextQL - GraphQL-liked engine which is similar to GraphQL but simpler.

My project supports complex nested type definitions, which free you from define a lot of useless ones.

ghickman
  • 5,893
  • 9
  • 42
  • 51
Giap Nguyen
  • 608
  • 7
  • 5
  • 6
    As a nitpicky aside, I don't see the sense in shortening 'Ticket' to 'Tick' in the suggest type 'TickGroupByAge'. It hurts the readability, and characters are cheap. – Gary Reckard Jan 30 '20 at 02:43
0

Check out https://github.com/niclasko/Cypher.js (note: I'm the author)

With relevance to the question. It can be used to query and aggregate over data from JSON endpoints:

load json from "http://url/person" as l return l.age, count(1)

There’s even a bar chart function:

load json from "http://url/person" as l return barchart(toint(l.age)) as age_distribution

Here's an example of querying a complex JSON document and performing aggregate analysis on it:

Cypher.js JSON query example