Steve
Steve

Reputation: 1515

Aliasing fields in Apollo GraphQL Server

Aliasing is very handy and works great when aliasing a specific resolver. For instance:

{
  admins: users(type:"admin"){
    username
  }
  moderators: users(type:"moderators"){
    moderators
  }
}

I'm not sure how to handle aliasing of the fields themselves though. For example:

{
  site_stats {
    hits: sum(field: "hits")
    bounces: sum(field: "bounces")
  }
}

If the resolver returns any sum value, the same value is aliased to both hits and bounces (which makes sense, since only a single sum value could even be returned). If I make the resolver use the alias names as the field names when returning the results, hits and bounces both become null.

I could simply break those fields out into separate resolvers, but that complicates integration for the front end devs. We would also lose a ton of efficiency benefits, since I can aggregate all the data needed in a single query to our data source (we're using ElasticSearch).

Any help from you geniuses would be greatly appreciated!

Upvotes: 0

Views: 2284

Answers (2)

xadm
xadm

Reputation: 8428

Using aliases and single fields has very limited usability.

You can use complex filters (input params), f.e. list of keys to be returned and their associated params, f.e.

[{name:"hits", range:"month"}, 
{name:"bounces", range:"year"}]

With query - expected structure

{
  stats {
    name
    sum
    average
  }
}

Required fields may vary, f.e. only name and sum.

You can return arrays of object f.e.

{ stats: [
  { name:"hits", 
    sum:12345, 
    average: 456 }

Aliases can be usable here to choose different data sets f.e. name and sum for hits, bounces additionally with average.

... more declarative?

PS. There is nothing that "complicates integration for the front end devs". Result is json, can be converted/transformed/adapted after fetching (clinet side) when needed.

Upvotes: 1

Daniel Rearden
Daniel Rearden

Reputation: 84867

It sounds like you're putting all your logic inside the root-level resolver (site_stats) instead of providing a resolver for the sum field. In other words, if your resolvers look like this:

const resolvers = {
  Query: {
    site_stats: () => {
      ...
      return { sum: someValue }
    },
  },
}

you should instead do something like:

const resolvers = {
  Query: {
    site_stats: () => {
      return {} // empty object
    },
  },
  SiteStats: {
    sum: () => {
      ...
      return someValue
    },
  },
}

This way you're not passing down the value for sum from the parent and relying on the default resolver -- you're explicitly providing the value for sum inside its resolver. Since the sum resolver will be called separately for each alias with the arguments specific to that alias, each alias will resolve accordingly.

Upvotes: 1

Related Questions