Count Queries in GraphQL

Another Possible Alternative to count queries

The approach of having a count variable inside queryData queries has the following disadvantages:

  1. It is a breaking change and will change queryData behaviour drastically.
  2. It also brings in other restrictions of not having any fields with the prefix of count , as count<FieldName> will be used to denote the count of predicate edges for <FieldName> field.

To avoid these two issues, as discussed with @pawan yesterday, we propose another approach to count queries.

Count at root

We can have another query of the name aggregate<type name>. This query will include fields for count and any other aggregation fields like sum or avg. For our current use-case, the updated schema would look like

input DataAggregateResult {
  count: Int
  ... 
  ...
  // Other fields for doing things like avg, sum, min, max etc.
}

query {
    aggregateData(filter: DataFilter): DataAggregateResult
}

Then the following GraphQL query

query {
  aggregateData(filter: {...}) {
    count
  }
}

would be rewritten to the following DQL query.

query {
    aggregateData(func: type(Data)) @filter(/* rewritten filter condtition */)) {
        count: count(uid)
    }
}

All query aggregation fields like sum, avg to be added later would be a part of return type of aggregateData query.

Count for a child

Along with the aggregateData query, to handle count of predicate edges and other aggregation fields, we propose having a <predicate_name>_aggregate field inside queryData query. This will solve the problem of having too many count<predicate_name> type fields inside the type.

For the following GraphQL schema

type Data {
  name: String!
  metaData: [Metadata]
}

Example:

query {
    queryData {
        name
        metaData_aggregate {
            count
        }
    }
}

The above query would be rewritten to DQL as follows.

query {
    queryData(func: type(Data))  {
        Data.name
        count(Data.metaData)   /* returns number of items in metaData list*/
    }
}

Note that the count(Data.metaData) field would be made a part of metaData_aggregate field while returning GraphQL response.

Other aggregation fields like min, max, sum could then be added later on to metaData_aggregate.
This approach is similar to how Aggregation queries are handled in other GraphQL providers.

@michaelcompton, I will like to hear your comments about this and any concerns you may have about the proposed solution.

2 Likes