Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return an array of objects in GraphQL, possibly using the same endpoint as the one that returns a single object?

I am making a GraphQL API where I would be able to retrieve a car object by its id or retrieve all the cars when no parameter is provided.

Using the code below, I am successfully able to retrieve a single car object by supplying id as a parameter.

However, in the case where I would expect an array of objects i.e. when I supply no parameter at all, I get no result on GraphiQL.

schema.js

let cars = [
  { name: "Honda", id: "1" },
  { name: "Toyota", id: "2" },
  { name: "BMW", id: "3" }
];

const CarType = new GraphQLObjectType({
  name: "Car",
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString }
  })
});

const RootQuery = new GraphQLObjectType({
  name: "RootQueryType",
  fields: {
    cars: {
      type: CarType,
      args: {
        id: { type: GraphQLString }
      },
      resolve(parent, args) {
        if (args.id) {
          console.log(cars.find(car => car.id == args.id));
          return cars.find(car => car.id == args.id);
        }
        console.log(cars);
        //***Problem Here***
        return cars;
      }
    }
  }
});

Test queries and their respective results:

Query 1

{
  cars(id:"1"){
    name
  }
}

Query 1 Response (Success)

{
  "data": {
    "cars": {
      "name": "Honda"
    }
  }
}

Query 2

{
  cars{
    name
  }
}

Query 2 Response (Fail)

{
  "data": {
    "cars": {
      "name": null
    }
  }
}

Any help would be much appreciated.

like image 859
Haris Ghauri Avatar asked Oct 12 '18 05:10

Haris Ghauri


People also ask

Can GraphQL query return multiple objects?

Hey Alex - yeah absolutely. You can return whatever you want from a GraphQL mutation as long as you specify it in the schema. If you wanted to return a reusable object, that's totally doable!

How do you return an object in GraphQL?

To declare a type that disallows null, the GraphQL Non‐Null type can be used. may return either a String or null. Only by explicitly specifying a field as non-null (in SDL, by appending a ! to the type), can we specify that a field should never return null.

What is __ Typename in GraphQL?

The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).


1 Answers

A Car and a List of Cars are effectively two separate types. A field cannot resolve to a single Car object one time, and an array of Car object another.

Your query is returning null for the name because you told it the cars field would resolve to a single object, but it resolved to an array instead. As a result, it's looking for a property called name on the array object and since one doesn't exist, it's returning null.

You can handle this in a couple of different ways. To keep things to one query, you can use filter instead of find and change the type of your query to a List.

cars: {
  type: new GraphQLList(CarType), // note the change here
  args: {
    id: {
      type: GraphQLString
    },
  },
  resolve: (parent, args) => {
    if (args.id) {
      return cars.filter(car => car.id === args.id);
    }
    return cars;
  }
}

Alternatively, you could split this into two separate queries:

cars: {
  type: new GraphQLList(CarType),
  resolve: (parent, args) => cars,
},
car: {
  type: CarType,
  args: {
    id: {
      // example of using GraphQLNonNull to make the id required
      type: new GraphQLNonNull(GraphQLString)
    },
  },
  resolve: (parent, args) => cars.find(car => car.id === args.id),
}

Check the docs for more examples and options.

like image 55
Daniel Rearden Avatar answered Oct 18 '22 07:10

Daniel Rearden