So far we can read our data, but there’s a good chance we need to edit our data records/documents. Any complete data platform needs a way to modify server-side data as well.
Imagine that a company has launched a new gadget. How would we go about adding the record to our database with GraphQL?
What Are Mutations?
Think of mutations like
PUT REST actions. Setting up a mutation is quite straightforward.
Let’s jump in!
Adding Records to Our Database
Create a file
Inside the file, we will place mutations.
- We’ll import the
GraphQLObjectTypeobjects from the GraphQL library.
- Import the GraphQL type for
- Import the
After importing the things we need, we can create the mutation.
A mutation is just a plain
GraphQLObjectType, like the query we had before. It has two main properties we’re interested in.
- The name of the mutation is what appears in the
2. Fields are where we can place our mutation logic.
Notice I added a new object inside the
fields object. It’s called
addGadget, and it will do exactly what it says it’ll do.
addGadget we have access to three properties,
addGadget type will be
gadgetGraphQLType. The gadget can only have properties that are allowed in the
gadgetGraphQLType type we declared earlier.
addGadget is a query that accepts arguments. The arguments are needed to specify which gadget we want to add to our database.
We declare up front which arguments the query accepts, and the types of the arguments.
Lastly — what happens with the query? This is precisely why we have the
resolve() function has two arguments:
args. We’re interested in the
args, since these are the values we pass to our query.
Inside the resolve, we place the logic for creating a new Mongo record.
We create a new instance of our
Gadget Mongoose model, pass the props we receive from GraphQL as new fields and finally save the record.
Here’s how the full mutation looks:
Voilà! All we need to do is import the mutation to our
If everything went fine, this is what we should see on our GraphiQL:
And if we click on it:
Notice how GraphQL automatically creates self-documentation.
Firing Off the Mutation Query
A mutation is just a plain GraphQL query, which takes our arguments, saves it to the Mongo database, and returns the properties we want.
Here’s the catch — every mutation needs to be marked as
We’ve successfully created and inserted a new gadget to our Mongo database.
If you head over to mLab, or whatever provider you’re using, you should see the new record.
Here’s the complete query for our mutation.
Editing Our Records in the Database
What if we want to edit pre-existing records? We can’t rely on never making a mistake, or what if the price changes?
Editing a record is also a mutation. Remember, every time we want to change/add a new record, it’s a GraphQL mutation!
graphql/mutations file and create another mutation. A mutation is just a plain object.
Notice the new mutation is called
updateGadget. It’s pretty much a replica of the previous mutation. Notice the extra argument, the
id — that’s because we need to find the existing gadget and change it. We can find the gadget by id.
resolve() function is where it gets more interesting. Ideally, we want to find the gadget by id, change the props, and save it. How would we go about doing this?
Mongoose gives us a method to do this, called
This returns a promise. If we
console.log the promise, we can see a huge blob of properties attached to it. What we can do with the promise, is chain it with a
So, we find the gadget, change the props, and save it. But this returns another promise that we need to resolve.
.catch() for error handling, in case we run into errors. Remember, you can monitor your
pm2 logs via the
pm2 logs command. If you run into errors, these will be logged to the pm2 logger.
That’s all! Query time. Look at your Mongo table and pick a random
id from there, then edit the corresponding gadget.
And if we inspect the database, we should see the edited record.
Here’s the query for the
Okay, so far we have the
Update, but we’re missing the final
Deleting a record from a Mongo database is quite straightforward. All we need is another mutation, since we are, in fact, mutating the database.
For deleting records, Mongoose gives us a handy method called
findOneAndDelete — you can read more about findOneAndDelete here.
Deleting the record just takes one argument — the id. We find the gadget by id, delete it, and return it. If there’s an error, we’ll log it.
And the query:
Note: Make sure the
id is correct and exists in the database, otherwise, it won’t work.
If we head over to our database and inspect it — indeed the record got deleted from our database.
Well done, we have achieved basic
CRUD functionality. Notice how GraphQL is a thin layer between our database and view. It’s not supposed to replace a database, but rather make it easier to work with data, fetching, and manipulating.
If you’re feeling good for GraphQL, I recommend reading through the “The Road to GraphQL” book for a more in-depth dive.
Here’s the source code:
Tutorial how to set up koa with graphql and mongodb - wesharehoodies/koa-graphql-mongodb
Don’t miss part three where we’ll do more great stuff:
How to set up a powerful API with GraphQL, Koa, and MongoDB — scalability, and testing
So far we achieved basic CRUD functionality.
Thanks for reading!