Search code examples
javascriptreactjsgraphqlrelayjsgraphql-js

How does Relay / GraphQL 'resolve' works?


I am trying out Relay and GraphQL. When I am doing the schema I am doing this:

let articleQLO = new GraphQLObjectType({
  name: 'Article',
  description: 'An article',
  fields: () => ({
    _id: globalIdField('Article'),
    title: {
      type: GraphQLString,
      description: 'The title of the article',
      resolve: (article) => article.getTitle(),
    },
    author: {
      type: userConnection,
      description: 'The author of the article',
      resolve: (article) => article.getAuthor(),
    },
  }),
  interfaces: [nodeInterface],
})

So, when I ask for an article like this:

{
  article(id: 1) {
    id,
    title,
    author
  }
}

Will it do 3 queries to the database? I mean, each field has a resolve method (getTitle, getAuthor, etc.) which does a request to the database. Am I doing this wrong?

This is an example of getAuthor (I use mongoose):

articleSchema.methods.getAuthor = function(id){
  let article = this.model('Article').findOne({_id: id})
  return article.author
}

Solution

  • If the resolve method is passed the article, can't you just access the property?

    let articleQLO = new GraphQLObjectType({
      name: 'Article',
      description: 'An article',
      fields: () => ({
        _id: globalIdField('Article'),
        title: {
          type: GraphQLString,
          description: 'The title of the article',
          resolve: (article) => article.title,
        },
        author: {
          type: userConnection,
          description: 'The author of the article',
          resolve: (article) => article.author,
        },
      }),
      interfaces: [nodeInterface],
    })
    

    Since Schema.methods in Mongoose defines methods on the model, it wouldn't take an ID for the article (because you call it on an article instance). So, if you wanted to keep the method, you would just do:

    articleSchema.methods.getAuthor = function() {
      return article.author;
    }
    

    If it was something you need to look up e.g. in another collection, then you'd need to do a separate query (assuming you're not using refs):

    articleSchema.methods.getAuthor = function(callback) {
      return this.model('Author').find({ _id: this.author_id }, cb);
    }