0
votes

I am looking to combine the results from two queries into one for my GraphQL schema. I have a stock and price type, each of which resolves individually but I don't know how to combine the results. Here is my typedefs and resolvers`:

const typeDefs = gql`
    type Query{
        stock(symbol: String!): Stock
        price(symbol: String!): Price
    }

    type Stock {
        companyName: String
        exchange: String
        industry: String
        sector: String
        tags: [String]
        cost: Price
    }

    type Price {
        cost: String
    }

`;

const resolvers = {
    Query:{
        stock: async(root, {symbol}, {dataSources}) =>{
            return dataSources.myapi.getSomeData(symbol)
        },
        // dont have a name for your property? ADD ONE!
        price: async(root, {symbol}, {dataSources})=>{
            return {'cost': dataSources.myapi.getAPrice(symbol)}
        }
    }
};

If I run a query like so, I get null for stock price:

query{
  stock(symbol:"aapl"){
    tags
    cost{
      cost
    }
  }
}

The result is like so:

{
  "data": {
    "stock": {
      "tags": [
        "Technology",
        "Consumer Electronics",
        "Computer Hardware"
      ],
      "cost": null
    }
  }
}

However, if I run a query for price, I get the expected outcome for the price:

query{
  price(symbol:"aapl"){
      cost
  }
}

I am using datasources and the file looks like so:

class MyApi extends RESTDataSource{
    constructor(){
        super();
        this.baseURL = 'https://api.iextrading.com/1.0';
    }

    async getAPrice(symbol){
        return this.get(`/stock/${symbol}/price`);
    }

    async getSomeData(symbol){
        return this.get(`/stock/${symbol}/company`)
    }
}

module.exports = MyApi;

I wanted to know why this is happening. Is there something that I am not doing well, or lack of understanding in a certain way GraphQL handles resolvers?

Would it be recommended to return both queries in the resolver through a promise? I am not sure where to go from here.

2

2 Answers

0
votes

I looked into this further and what you referred to as the "bottom stock block" is called a nested resolver in GraphQL terms. Here is what I came up with for my additional resolver:

Stock:{
    price: async(company, args, {dataSources})=>{
        return {'cost': dataSources.myapi.getAPrice(company.symbol)}
    }
}

Does this seem to be the same thing?

0
votes

I believe what you have will work with the following adjustment to your resolvers:

const resolvers = {
    Query: {
        stock: async(root, {symbol}, {dataSources}) => {
            const stock = await dataSources.myapi.getSomeData(symbol)
            return {...stock, symbol: symbol}
        },
        // dont have a name for your property? ADD ONE!
        price: async(root, {symbol}, {dataSources}) => {
            const cost = await dataSources.myapi.getAPrice(symbol)
            return {cost: cost}
        }
    },
    Stock: {
      cost: async (stockWithSymbol, args, {dataSources}) => {
        const cost = await dataSources.myapi.getAPrice(stockWithSymbol.symbol)
        return {cost: cost}
      }
    }
};

The bottom Stock block tells GraphQL how to resolve the cost field on the Stock type. Notice that in the root stock query resolver, I'm also spreading the response with the symbol so that it is available in the first argument of the cost field resolver. You may have a better way of loading price given the stock information, but just going off the schema shown.