user1935987
user1935987

Reputation: 3347

graphql passing dynamic data to mutation

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!

Upvotes: 1

Views: 1293

Answers (1)

Greg Brodzik
Greg Brodzik

Reputation: 1817

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

Upvotes: 1

Related Questions