What can be the best way to resolve the data in GraphQL
Here i have a SeekerType and JobType, JobsType is nested in SeekerType
A Seeker can apply to many Jobs. When Querying for a seeker, One can just query for seeker's data or as well as he can query for nested JobType and can get the jobstype data too.
But the Question is that If One doesn't Query for nested JobType
he won't get the Jobs data but mine Seeker resolver in viewerType would be fetching that data too.
So, while providing data to the seeker query how can i handle that, Either he can only want seeker details or may want the jobs details too.
Shall I use resolver of each nestedType and get the parent object, and fetch the relevant data using fields from parent Object???
The code below is just for illustration and clarification, the question is about the best way to resolve data
ViewerType.js
const Viewer = new GraphQLObjectType({
name: 'Viewer',
fields: () => ({
Seeker: {
type: SeekerConnection,
args: _.assign({
seekerId: { type: GraphQLID },
status: { type: GraphQLString },
shortlisted: { type: GraphQLInt },
}, connectionArgs),
resolve: (obj, args, auth, rootValue) => {
const filterArgs = getFilters(args) || {};
return connectionFromPromisedArray(getSeekers(filterArgs), args)
.then((data) => {
// getSeekers() provides all the data required for SeekerType fields and it's
JobsType fields
data.args = filterArgs;
return data;
}).catch(err => new Error(err));
},
},
}),
});
SeekerType.js
const SeekerType = new GraphQLObjectType({
name: 'SeekerType',
fields: () => ({
id: globalIdField('SeekerType', obj => obj._id),
userId: {
type: GraphQLID,
resolve: obj => obj._id,
},
email: { type: GraphQLString },
password: { type: GraphQLString },
firstName: { type: GraphQLString },
lastName: { type: GraphQLString },
imageLink: { type: GraphQLString },
education: { type: GraphQLString },
address: { type: GraphQLString },
jobs: {
type: new GraphQLList(JobType),
},
}),
interfaces: [nodeInterface],
});
getSeekers() provide complete data as graphql fields format with nested
jobs field data too
const getSeekers = filterArgs => new Promise((resolve, reject) => {
if (Object.keys(filterArgs).length === 0) {
Seeker.find(filterArgs, { password: 0 }, (err, d) => {
if (err) return reject(err);
return resolve(d);
});
} else {
async.parallel([
(callback) => {
filterArgs._id = filterArgs.seekerId;
delete filterArgs.seekerId;
Seeker.find(filterArgs).lean()
.exec((err, d) => {
if (err) return callback(err);
if (err === null && d === null) return callback(null);
callback(null, d);
});
},
(callback) => {
filterArgs.seekerId = filterArgs._id;
delete filterArgs._id;
Applicant.find(filterArgs).populate('jobId').lean()
.exec((err, resp) => {
if (err) return callback(err);
callback(null, resp);
});
},
], (err, data) => {
const cleanedData = {
userData: data[0],
userJobMap: data[1],
};
const result = _.reduce(cleanedData.userData, (p, c) => {
if (c.isSeeker) {
const job = _.filter(cleanedData.userJobMap,
v => _.isEqual(v.seekerId, c._id));
const arr = [];
_.forEach(job, (i) => {
arr.push(i.jobId);
});
const t = _.assign({}, c, { jobs: arr });
p.push(t);
return p;
}
return reject('Not a Seekr');
}, []);
if (err) reject(err);
resolve(result);
// result have both SeekerType data and nested type
JobType data too.
});
}
});