Create a custom FindOrCreate resolver
First off, thank you so much for the awesome work done here. So much cool stuff!
My issue is around creating a findOrCreate Graphql-compose custom resolver. The goal is basically checking before creation if the item exists. If so, the resolver should only return the existing item otherwise create it.
Is that possible, using uniquely pre-built resolvers?
Here is what i have tried:
_UserTC.addResolver({
name: 'findOrCreate',
type: _User.getResolver('createOne').getType(),
args: _User.getResolver('createOne').getArgs(),
resolve: ({ source, args, context, info }) => {
User.findOne(args.record , (err, user) => {
if (user)
return user;
else {
user = new User (args.record)
return user;
}
})
}
})
Thank you in advance!
Yep, it possible. You almost did the trick. The following solution should work:
_UserTC.addResolver({
name: 'findOrCreate',
kind: 'mutation',
type: _User.getResolver('createOne').getType(),
args: _User.getResolver('createOne').getArgs(),
resolve: ({ source, args, context, info }) => {
// must return result
return User.findOne(args.record).then(user => {
// check or create new user
if (user) return user;
return User.create(args.record);
}).then(user => {
// return to resolver proper shape of data (how in described in _User.getResolver('createOne').getType() )
return {
record: user,
recordId: _UserTC.getRecordIdFn()(user)
};
});
}
});
The same code with async/await:
_UserTC.addResolver({
name: 'findOrCreate',
kind: 'mutation',
type: _User.getResolver('createOne').getType(),
args: _User.getResolver('createOne').getArgs(),
resolve: async ({ source, args, context, info }) => {
let user = await User.findOne(args.record).exec();
if (!user) user = await User.create(args.record);
return {
record: user,
recordId: _UserTC.getRecordIdFn()(user)
};
}
});
You miss just one thing - resolve function must return some data. And the shape of this data must have the same shape (fileds and types) which provided to type: _User.getResolver('createOne').getType(),.
Forgot to say you about finding existed record
User.findOne(args.record)
will not work properly if you have nested fields eg. geo: { loc: 1, lat: 3 }. For mongoose you should provide such filter { 'geo.loc': 1, 'geo.lat': 3}.
As result better to define filter explicitly by your fields which you use for determining record uniqueness:
User.findOne({ isbn: args.record.isbn, 'geo.lat': args.record.geo.lat })
Working like a charm! Thank you so much 🙏
I wish I could say the same. I'm getting a nasty User.getResolver is not a function error in my console.
@nparsons08 please open a new issue with your code. It's look like that you have syntax error or wrong imports.