Is it possible to fields using another query in graphQl ?
For eg., consider I have below schema
type Query {
getVehicles: Vehicles
getCars: [Car!]
getBuses: [Bus!]
getTrucks: [Truck!]
}
type Vehicles {
cars: [Car!]
buses: [Bus!]
trucks: [Truck!]
}
type Car {
plate: String
}
type Bus {
plate: String
}
type Truck {
plate: String
}
Is it possible to have something like
type Vehicles {
cars: getCars()
buses: getBuses()
trucks: getTrucks()
}
so that getCars()
will be triggered only when the request field has the cars selected.
I am trying to do an on demand fetching so that we don't have to fetch all 3 when the request contains a sub selection.
I am using com.netflix.graphql.dgs
:graphql-dgs-spring-graphql-starter
So, my server is implemented using java with com.netflix.graphql.dgs.DgsComponent
and com.netflix.graphql.dgs.DgsQuery
edit: Additional question. How can we propagate the input field for first query to the second one ?
getVehicles(state: String!): Vehicles
type Vehicles {
cars(state: String!): [Car!]
buses(state: String!): [Bus!]
trucks(state: String!): [Truck!]
}
@DgsQuery
public Vehicles getVehicles(@InputArgument String state) {
return new Vehicles(); // Return an empty object; fields are resolved lazily
}
@DgsData(parentType = "Vehicles", field = "cars")
public List<Car> getCars(DgsDataFetchingEnvironment dfe, @InputArgument String state) {
System.out.println("Fetching cars...");
return List.of(new Car("CAR123"), new Car("CAR456"));
}
Your Schema(GraphQL):
type Query {
getVehicles: Vehicles
getCars: [Car!]
getBuses: [Bus!]
getTrucks: [Truck!]
}
type Vehicles {
cars: [Car!]
buses: [Bus!]
trucks: [Truck!]
}
In your GraphQL server, you define resolvers for the Vehicles
type like this (Javascript):
const resolvers = {
Query: {
getVehicles: () => ({}), // return an empty object or context
},
Vehicles: {
cars: () => getCars(), // only called if 'cars' is requested
buses: () => getBuses(), // only called if 'buses' is requested
trucks: () => getTrucks() // only called if 'trucks' is requested
}
};
Example:
query {
getVehicles {
cars {
plate
}
}
}
Only the cars resolver will be triggered in this case.
Model Class:
public class Car {
private String plate;
}
public class Bus {
private String plate;
}
public class Truck {
private String plate;
}
public class Vehicles {
// optional fields
}
Resolver (Query)
@DgsComponent
public class VehiclesQuery {
@DgsQuery
public Vehicles getVehicles() {
return new Vehicles(); // Return an empty object; fields are resolved lazily
}
}
Field Resolvers
@DgsComponent
public class VehiclesDataFetcher {
@DgsData(parentType = "Vehicles", field = "cars")
public List<Car> getCars(DgsDataFetchingEnvironment dfe) {
System.out.println("Fetching cars...");
return List.of(new Car("CAR123"), new Car("CAR456"));
}
@DgsData(parentType = "Vehicles", field = "buses")
public List<Bus> getBuses(DgsDataFetchingEnvironment dfe) {
System.out.println("Fetching buses...");
return List.of(new Bus("BUS789"));
}
@DgsData(parentType = "Vehicles", field = "trucks")
public List<Truck> getTrucks(DgsDataFetchingEnvironment dfe) {
System.out.println("Fetching trucks...");
return List.of(new Truck("TRUCK321"));
}
}
Only the getCars()
method will be triggered. The others (getBuses
, getTrucks
) will not be called unless explicitly requested.
Hopefully, this should resolve your issue