Open riggedCoinflip opened 3 years ago
Interesting idea 👍
But the current suggested implementation looks now like a hack. And it can bring a lot of problems in the future when we want to migrate on InputUnions or refactor the suggested solution without breaking changes. Now it just brings complexity to the current resolver implementation. But right now record
& options
will not cover all user cases – what if we need to unset some fields?! So I think that we need provide some solution that will cover 95% of different uses cases with mongodb operators (push, pop, set, unset, ...) https://docs.mongodb.com/manual/reference/operator/update/
I think we need to await @oneOf
implementation https://github.com/graphql/graphql-spec/pull/825 which unlocks InputUnions, and we can use it for the current or similar issues.
ANYWAY I'm glad to see any suggestion because BEST PRACTICES arise only in the "battle" (practice, implementation, design, discussions). But we should avoid any modifications until we do not become sure that it's a good solution for most developers. Better not to do something rather than provide a temporary thing.
@riggedCoinflip, as a workaround I suggest you write a custom resolver with any desirable logic.
I went for the custom resolver.
This snippet allows to push and pop MongoIDs from a block list and allows certain other fields to be updated.
schemaComposer.createInputTC({
name: "UserPrivateBlockedMutation",
fields: {
toPush: ["MongoID"],
toPop: ["MongoID"],
}
})
UserTCPrivate.addResolver({
kind: "mutation",
name: "userUpdateSelf",
description: "Update currently logged in user",
args: {
name: "String",
gender: "EnumUserPrivateGender",
blocked: "UserPrivateBlockedMutation",
},
type: UserTCPrivate,
resolve: async ({args, context}) => {
/**
* @param {Array} arr - array to filter
* @param {Array} values - values to filter out
* @returns {Array} filtered
*/
function filterByValues(arr, values) {
return arr.filter(
itemArray => { !values.some(itemValues => itemArray.equals(itemValues)})
}
const userSelf = await User.findOne({_id: context.req.user._id})
if (args.name) userSelf.name = args.name
if (args.gender) userSelf.gender = args.gender
if (args.blocked?.toPush) userSelf.blocked.push(...args.blocked.toPush)
if (args.blocked?.toPop) userSelf.blocked = filterByValues(userSelf.blocked, args.blocked.toPop)
await userSelf.save()
return User.findOne({_id: context.req.user._id})
}
})
Query:
#Template Query
mutation userUpdateSelf(
$name: String
$gender: EnumUserPrivateGender
$blocked: UserPrivateBlockedMutation
) {
userUpdateSelf(
name: $name
gender: $gender
blocked: $blocked
) {
name
gender
blocked
}
}
#Example
mutation {
userUpdateSelf(
name: "MyNewName"
gender: female
blocked: {
toPush: ["MongoIDsOfUsersYouWishToBlock"]
toPop: ["MongoIDsOfUsersInYourBlocklist"]
}
) {
name
gender
blocked
}
}
Let's say I have a Schema like this:
And I want to update an existing Document - from what I know currently we only have the option to replace our fields with new ones. Are there any options to
Example push: I have a document
and want to add
"d"
to the array.Currently I would need to
which would cost many recources
or
which I see problematic if we have Schemas with multiple arrays and we want to allow mutations like
Same Problems exist with popping elements.
I think it would be great if we had some kind of options in the Mutation itself. It would be super neat if we had a syntax that allows stuff like this:
I know this is asking for extremely much, but perhaps I inspire someone to implement something like it. My skills unfortunately aren't high enough to do it myself.