Apollo server: the connector and model layer

by

In this tutorial we’ll continue where we left off in our Apollo Starter guide. If you did that one you can just continue using that project, if not you can clone this repository:

I already added the folder structure I wish to use on my Apollo server. it includes 4 layers. Starting from the top:

  1. Schema
  2. Resolvers
  3. Models
  4. Connectors

We are going to be focusing on the model and connector layers. The model layer is what our resolvers are gonna use. They are there to expose a generic interface to our resolvers that have abstracted whatever database and possible ORM used in the connectors layer.

The connectors layer exposes functions to manipulate data which the model layer uses. These functions interfaces depend upon what database or ORM is chosen. It also takes care of setting up the different connections to databases.

We already made the schema and a couple of resolvers in the previous tutorial. So let’s start from the bottom this time with the connectors layer.

The connectors layer

We are going to set up a MongoDB connection in the connectors layer. We’ll use Mongoose for easier collection manipulation. So let’s start by adding Mongoose to our project.

npm install mongoose --save

If you don’t have MongoDB installed you can find it in the MongoDB Download Center.

When it is installed you should be able to run it from the command line with this command

Windows: mongod --dbpath=C:/data --port 27017

OSX: mongod --port 27017

You can also get a free 500mb mongodb at mLab and use that one instead of a local one…

In the index.js file of the connectors folder we are going to setup the connection to a Mongo database called “test” on port 27017 which is the default port. We do that like so:

Besides making a connection we also create 2 schemas and models using Mongoose. When we think back on our schema, the user type had an array of cars. Like I mentioned earlier, the schema doesn’t represent the data model. Our mongoose schema for users doesn’t have a cars array. But we do have a Car. We’ll connect the dots in the User resolver later.

The models layer

Let’s start by creating a user.js file inside the models folder. In this file we’ll import the User from the connectors layer, define a couple of functions and export a User object with those functions. Like this:

So with this we can now import  User from the models layer, into our resolvers layer and start creating and finding users.

We’ll need a car.js file as well for the Car model. They are similar but  Car will have a function that can find them by their owners id.

Now we just need the index.js  file to export Car and User for easier importing.

We should now be ready to fix our resolve functions!

Splitting up the resolver

But our resolvers was all in 1  .js file. I showed you how you could split up your schema into several pieces instead of keeping them all in 1 file. We are going to be doing the same thing here.

Let’s create a user.js file inside of the resolvers folder to hold the user resolve function. Most of the code we need is already written in the resolvers.js file. We just add it to a constant and expose it. Oh and we also remove the mocked return value and actually fetch the data through our models layer!

We are also gonna make a query.js file inside the resolvers folder and put the query resolve functions inside. Again we remove the mocked return value.

We also wanna add 2 mutations. One to create a car and one to create a user. query are gets. They are used to fetch data. When you wanna manipulate data you wanna do a post. That’s what Mutations are. Create a mutation.js file in the resolvers folder.

Now that it’s done we can export them in the index.js file and remove our resolver.js file because that won’t be needed anymore! Where we import the resolvers are now pointing on the resolvers folders index file instead of the resolvers.js file we removed. So everything should work exactly like before. The index.js file should look like this:

But we forgot 1 thing. Our schema doesn’t expose our mutations yet! Create a mutation.graphql file inside the schema folder and paste this inside:

Now notice that they take inputs of type InputUser and InputCar. That is because when you want to pass custom types as function params they need to be of type input. I usually put these input types right next to their respective types. So inside of the car.graphql file add the input type

And also inside of the user.graphql file like so:

Alright we are almost done! we need to add the mutations to the schemaDefinition.graphql file!

And as the final thing we need to import it in the index.js file and add it to the exported array. It should look like this when your done:

Testing

FINALLY! Now let’s test it out! Try hitting up GraphiQL at http://localhost:8080/graphiql and copy paste the following into it:

Now we got 3 functions to play with. First hit the big play button and select createUser.

It should return the newly created user with an _id param. Take that param and paste it inside of the createCar and getUser functions on the empty strings place.

Now let’s try getUser. It should return the user you already received from createUser, but with an empty cars array. Try hitting createCar now. That creates a car in our database with the owner set to the user we created (if you remembered to paste in the id).

Play around with it and try adding your own functions! 🙂

You can view the source right here: https://github.com/CaveOfCodeBlog/simple-apollo-server

That was all for this tutorial. If you liked it or have any questions feel free to leave a comment below!

  • HaveFHaveF

    Very happy to read these two articles. Especially I studied a lot about the folder structure part. Thanks!

    • Jesper Christensen

      Very happy that you found it useful! 🙂

  • This was extremely helpful. Any chance you can continue and add another tutorial that shows how to use the data with React and Redux?

    • Jesper Christensen

      Glad you like it! Even through i do like React and Redux a lot. It is not on the table right now unfortunately. If i find time ill finish my Apollo TypeScript tutorial 🙂

  • Kim Gabrielsen

    Thank you for a very good and thorough tutorial.

    I have one question though. When i run the sample my date field is correctly saved as an iso date in the database. But when i query it it’s returned in a strange non-iso format in GraphiQL. How do i ensure that the date returned will display as an ISO date?

    I have tried to

    import {
    GraphQLDate,
    GraphQLTime,
    GraphQLDateTime
    } from ‘graphql-iso-date’;

    in the index.js and use a GraphQLDate as type on the birthday field. But it says that GraphQLDate,in not known.

    do you have a suggestion on how to solve this?