Features: createMany, mutation for an existing array
hello~
Do we have plan to add createMany, and recordIds returns the array of ObjectIDs, records returns the updated objects.
//createMany
var array = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
Movies.insertMany(array, function(error, docs) {});
Could we support mutation for updating an array field if I pass an ObjectId that adding to the existing array instead of overwrite, the overwrite only happens if I pass an array of ObjectId?
The first mutation for phones and returns two values for phones being "111-222-333-444", "444-555-666-777".
mutation {
userCreate(record: {
contacts: {
phones: [
"111-222-333-444",
"444-555-666-777"
]
},
}) {
recordId
record {
contacts {
email
phones
}
}
}
}
{
"data": {
"userCreate": {
"recordId": "593ca1149f15dd003778ba1f",
"record": {
"contacts": {
"email": null,
"phones": [
"111-222-333-444",
"444-555-666-777"
]
}
}
}
}
}
The second mutation for phones, the expected returns are three values for phones being "111-222-333-444", "444-555-666-777", "444-555-666-888" instead of "444-555-666-888".
mutation {
userCreate(record: {
contacts: {
phones: "444-555-666-888"
},
}) {
recordId
record {
contacts {
email
phones
}
}
}
}
{
"data": {
"userCreate": {
"recordId": "593ca1149f15dd003778ba1f",
"record": {
"contacts": {
"email": null,
"phones": [
"111-222-333-444",
"444-555-666-777",
"444-555-666-888"
]
}
}
}
}
}
thanks, anderson
createMany resolver make sense. Can you make PR? Just copy https://github.com/nodkz/graphql-compose-mongoose/blob/master/src/resolvers/createOne.js and its tests and make situable changes. It will be awesome.
About pushing value to array I need to think a little bit more. Cause when we create such resolver, somebody else wants to pop resolver and bunch of others. And with time this lib becomes fat. Anyway you may create custom resolvers in TC to get it working right now in your code:
UserTC = myCustomHelper(composeWithMongoose(UserModel));
function myCustomHelper(tc) {
tc.setResolver('pushToArray', new Resolver(...));
tc.setResolver('somethingElse', ...);
return tc;
}
Write your helpers and compose types 😉 If you write such helpers fill free to share it with me for review, maybe some parts goes to docs.
Or such
UserTC = extendedComposeWithMongoose(UserModel);
Function extendedComposeWithMongoose(mongooseModel) {
const tc = composeWithMongoose(mongooseModel);
tc...
return tc;
}
In case this is useful for anybody from the future I implemented such a resolver:-
MessageTC.addResolver({
name: 'pushToArray',
type: MessageTC,
args: { id: 'MongoID!', readBy: '[MongoID]' },
resolve: async ({ source, args, context, info }) => { // only used args but keeping for clarity
const message = await Message.update({ _id: args.id }, { $addToSet: { readBy: { $each: args.readBy } } })
if (!message) return null
return Message.findOne({ _id: args.id })
}
})
This takes an id to update and an array of MongoIDs to add to an existing field 'readBy'. I use $addToSet which will add unique elements to the array only. If you don't care about duplicates use $push instead.
Don't forget to .addFields({myField: MessageTC.getResolver('pushToArray')})
@nodkz might be worth mentioning this approach in the docs as I expect it is a fairly common use case and I spent a few hours before reaching this thread and the above solution
Also what's the difference between addResolver and setResolver I wasn't clear from the docs. Thank you.
@mattslight feel free to open PR and add this in README's FAQ 🙏
About difference in methods:
-
addResolver(opts)- use under the hoodsetResolvermethod;optscan be aResolverobject or options for resolver creation{ name: , kind: , resolve: , args: , ... }. This methods create resolver if needed, takes its name and pass to.setResolver(resolver.name, resolver). -
setResolver(name: string, resolver: Resolver)add resolver with provided name, which may differ from internal Resolver name
eg.
const r = Resolver({ name: 'findMany', ... });
UserTC.setResolver('fm', r); // will add resolver under name `fm`
UserTC.addResolver(r); // will add resolver under original name `findMany`
Very hidden but usefull difference.
@nodkz FAQ updated and PR sent, I tidied the example up and I didn't use your function wrapper example as per below, as I figured that even though it is more reusable it is a slightly more advanced approach.
UserTC = myCustomHelper(composeWithMongoose(UserModel));
function myCustomHelper(tc) {
tc.setResolver('pushToArray', new Resolver(...));
tc.setResolver('somethingElse', ...);
return tc;
}
@mattslight yep, I'm widely using similar helpers like myCustomHelper in my App when I need a reusble specific logic in many types. Exactly for such things was designed graphql-compose.