1

haven't used graphql or mongodb previously. What is the proper way to pass objects for the update mutation?

Since the only other way i see to pass multiple dynamically appearing parameters is to use input type which is appears to be a bit ineffective to me (in terms of how it looks in the code, especially with bigger objects), i just pass the possible values themselves. however in this case i need to dynamically construct updateObject, which again, going to get messy for the bigger models.

for example now i did:

Mutation: {
        updateHub: async (_, { id, url, ports, enabled }) => {
            const query = {'_id': id};
            const updateFields = {
                ...(url? {url: url} : null),
                ...(ports? {ports: ports} : null),
                ...(enabled? {enabled: enabled} : null)
            };
            const result = await HubStore.findByIdAndUpdate(query, updateFields);
            return {
                success: !result ? false : true,
                message: 'updated',
                hub: result
            };
        }
}

any advise on the better way to handle this?

thanks!

1 Answer 1

1

It appears your code could benefit from using ES6 spread syntax -- it would permit you to deal with an arbitrary number of properties from your args object without the need for serial tertiary statements.

Mutation: {
        updateHub: async (_, { id, ...restArgs } ) => {
            const query = {'_id': id};
            const updateFields = { ...restArgs };
            const result = await HubStore.findByIdAndUpdate(query, updateFields);
            return {
                success: !result ? false : true,
                message: 'updated',
                hub: result
            };
        }
}

If for some reason you need to explicitly set the undefined properties to null in your object, you could possibly use some a config obj and method like defaults from the lodash library as shown below:

import { defaults } from 'lodash';
const nullFill = { url: null, ports: null, enabled: null }; // include any other properties that may be needed

Mutation: {
        updateHub: async (_, { id, ...restArgs } ) => {
            const query = {'_id': id};
            const updateFields = defaults(restArgs, nullFill);
            const result = await HubStore.findByIdAndUpdate(query, updateFields);
            return {
                success: !result ? false : true,
                message: 'updated',
                hub: result
            };
        }
}

Also, FWIW, I would consider placing the dynamic arguments that could be potentially be updated on its own input type, such as HubInput in this case, as suggested in the graphql docs. Below I've shown how this might work with your mutation. Note that because nothing on HubInput is flagged as requird (!) you are able to pass a dynamic collection of properties to update. Also note that if you take this appraoch you will need to properly destructure your args object initially in your mutation, something like { id, input }.

    input HubInput {
       url: String
       ports: // whatever this type is, like [String]
       enabled: Boolean
       // ...Anything else that might need updating
     }

     type UpdateHubPayload {
        success: Boolean
        message: String
        hub: Hub // assumes you have defined a type Hub
     }

     updateHub(id: Int, input: HubInput!): UpdateHubPayload
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for such detailed response! i guess i missed that the spread operator can be used in such way, cool! could u please elaborate on possible implementation of the separate type for the dynamic arguments? i guess that'll be useful not only for me.
@user1935987 I've added to and refined my answer above in response to your request - hope this helps.
ahh ok, you mean to use the input graphql type. probably misunderstood you. yeah, that is a possible solution, however personally don't want to use it since it'll add a lot more code, especially for the larger objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.