The Ultimate Beginner’s Guide to GraphQL: Part 2 – Organization, Parameters, more Queries, and Mutations
Tags: graphql, node, javascript, database
Published: 2020-12-20 01:49:03

Hi everyone! Welcome back to part 2 of **The Ultimate Beginner’s Guide to GraphQL** tutorial series. Before we start, if you haven’t seen [part 1](https://thejavascriptninja.com/the-ultimate-beginners-guide-to-graphql/), you might want to check it out [here](https://thejavascriptninja.com/the-ultimate-beginners-guide-to-graphql/). This tutorial will build off the concepts learned in [part 1](https://thejavascriptninja.com/the-ultimate-beginners-guide-to-graphql/).

With all that said, I wanted to go more in-depth about something I only briefly mentioned in part 1: the GraphQL infrastructure. This is an important part of learning how GraphQL works, and what makes it so awesome.

#The GraphQL Infrastructure

To get a better understanding of the advantages and disadvantages of GraphQL, I created this handy little infographic:

![graphql_infographic](https://i0.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/gql-page-001-copy-scaled.jpg?resize=768%2C1920&ssl=1)

Alright! Hopefully that gives you a little insight into the inner workings of GraphQL, and helps you understand some of the operations at a deeper level.

#Organizing the Code

Unfortunately, before we get to the fun stuff in this tutorial, we do have to work through the boring stuff. This means working on organizing our code.

If you don’t remember, we used our standard server code and made some significant changes to the `index.js` file in [part 1](https://thejavascriptninja.com/the-ultimate-beginners-guide-to-graphql/) of the tutorial. I’d recommend reading that part first so you’ll be up-to-date on what we’re doing. After completing part 1, the code in our index.js file should look like this:

```
const port = process.env.port || 3000;
const express = require('express');
const ejs = require('ejs');
const layouts = require('express-ejs-layouts');
const app = express();

app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use(layouts);

const homeController = require('./controllers/homeController.js');
app.get('/', homeController.renderIndex);

const { gql } = require('apollo-server-express');
const schema = gql`
  type Query {
    getUsers: User
  }
  type User {
    id: Int!
    username: String!
    email: String!
    password: String!
  }
`;

let users = [
  {
    id:1,
    username:'The Javascript Ninja',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
  {
    id:2,
    username:'The Javascript Ninjas Best Friend',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
]

const resolvers = {
  Query: {
    getUsers: _ => 'Hello World'
  }
}

const { ApolloServer } = require('apollo-server-express');
const serve = new ApolloServer({
  typeDefs: schema,
  resolvers: resolvers,
});
serve.applyMiddleware({ app });

const server = app.listen(port, () => {
  console.log(`🚀 Server listening on port ${port}`);
});
```

For a full explanation, read [part 1](https://thejavascriptninja.com/the-ultimate-beginners-guide-to-graphql/). Otherwise, note that the code above will create a GraphQL server alongside our express server, and define a simple query to execute. Don’t leave yet – read on. We’ll be expanding this database model later in the tutorial.

Since we’ll be greatly expanding the code in our `index.js` file, it might do us some good to split it up between other files. This will reduce the amount of clutter in our main file, and keep our project file organized.

To organize our code, we can move our `schema` and `resolvers` objects to separate files. This may seem a little overkill at first, but after we expand them, it will be totally necessary.

To do this, first, create a `models` folder at the root level of your project. We will still want everything in our project to correspond with [MVC formatting](https://thejavascriptninja.com/what-is-the-mvc/).

Then, in our new `models` folder, we’ll create the files `schema.js` and `resolvers.js`.

Next, in `schema.js`, cut and paste the `schema` object from index.js:

```
const { gql } = require('apollo-server-express');
const schema = gql`
  type Query {
    getUsers: User
  }
  type User {
    id: Int!
    username: String!
    email: String!
    password: String!
  }
`;
```

Then, in `resolvers.js`, cut and paste the `resolvers` object and `users` array from `index.js`:

```
let users = [
  {
    id:1,
    username:'The Javascript Ninja',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
  {
    id:2,
    username:'The Javascript Ninjas Best Friend',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
];

const resolvers = {
  Query: {
    getUsers: _ => users;
  }
}
```

Then, modify `index.js` so it looks like this:

```
const port = process.env.port || 3000;
const express = require('express');
const ejs = require('ejs');
const layouts = require('express-ejs-layouts');
const app = express();

app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use(layouts);

const homeController = require('./controllers/homeController.js');
app.get('/', homeController.renderIndex);

const schema = require('./models/schema.js');
const resolvers = require('./models/resolvers.js');

const { ApolloServer } = require('apollo-server-express');
const serve = new ApolloServer({
  typeDefs: schema,
  resolvers: resolvers,
});
serve.applyMiddleware({ app });

const server = app.listen(port, () => {
  console.log(`🚀 Server listening on port ${port}`);
});
```

Awesome! Now our code is all nice and organized. All that we’ve done above is just sort our `resolvers` and `schema` objects into modules so they don’t all clutter up the same file.

#Writing More Advanced Queries With Parameters

Alright, now it’s time to work on the meat of GraphQL: querying. Querying is arguably the biggest and most important part of GraphQL (partly because the QL stands for Query Language). But, with all that said, it’s time to focus on writing more advanced query functions. The queries we wrote in part 1 were great, but they couldn’t do much and left a lot to be desired.

In a realistic situation, your GraphQL query is probably going to return a lot of data. There are multiple reasons why this could be bad:

• It’s hard to comprehend
• It will drastically slow down the site
• It’s impossible to filter through or perform operations on

As you can see, none of these options are good in the slightest. That’s why it’s important to write better queries by filtering through data to return only what we need, not the entire database. We can do this by adding query parameters.

###Adding In Some Parameters

To add some parameters to our query, navigate to your `schema.js` file.

Then, let’s add some parameters to the `getUsers` query in the `Query` type.

```
const { gql } = require('apollo-server-express');
const schema = gql`
  type Query {
    getUsers(id:Int, username:String, email:String, password:String): User
  }
  type User {
    id: Int!
    username: String!
    email: String!
    password: String!
  }
`;
```

As you can see, we added all the arguments we wanted available to the `getUsers` query. The reason I’ve added these arguments is so I’ll be able to filter through different users by these specific fields. There are no exclamation points after the object types in the parameters because I want all parameters to be optional.

However, before we can successfully execute our query with these parameters, we need to make some edits to our resolvers.

Go to `resolvers.js`. Let’s update our `getUsers` resolver. Right now, it looks like this:

```
let users = [
  {
    id:1,
    username:'The Javascript Ninja',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
  {
    id:2,
    username:'The Javascript Ninjas Best Friend',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
];

const resolvers = {
  Query: {
    getUsers: _ => 'Hello World'
  }
}
```

Pretty lame, huh? Right now, this lame resolver can only return our pre-set array of objects. And even at that, we can’t even filter the results in our query.

Well, it’s time for things to change. Update `resolvers.js` so it looks like the following:

```
let users = [
  {
    id:1,
    username:'The Javascript Ninja',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
  {
    id:2,
    username:'The Javascript Ninjas Best Friend',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
];

const resolvers = {
  Query: {
    getUsers: (parent, args) => {
      if (args.id) {
        return users.filter(user => user.id === args.id);
      } else if (args.username) {
        return users.filter(user => user.username === args.username);
      } else if (args.email) {
        return users.filter(user => user.email === args.email);
      } else if (args.password) {
        return users.filter(user => user.password === args.password);
      } else {
        return users;
      }
    }
  }
}
```

Wow – Big improvement. However, there’s a lot going on; let me explain it for you:

**1.** First, the `getUsers` method takes in two parameters: `parent`, and `args`. It is important that `args` be the second parameter, otherwise you will get an error.

**2.** Second, we make a long `if` statement. First, we check if the arguments `id`, `username`, `email`, or `password` were provided to filter through the data. If no parameters were provided, we return all the data in the users array.

**3.** If parameters were provided with the query, we filter through the data in the `users` array with the `array.filter()` method. Then, we return matching data – if there is any.

Now, let’s test our new-and-improved query. Run your server and navigate to `localhost:3000/graphql`.

![img](https://i1.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-16-at-8.43.32-PM.png?resize=768%2C331&ssl=1)

Then, enter the following query into the box on the left:

```
query {
  getUsers(id:1) {
    id
    username
    email
    password
  }
}
```


This should retrieve all data for the user with an id equal to 1.

![img](https://i0.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-16-at-8.48.17-PM.png?resize=768%2C331&ssl=1)

#GraphQL Mutations

The next big part of GraphQL is modifying data in the database. This includes adding and deleting users, in our scenario. Fortunately, GraphQL provides an easy way for us to do this: mutations.

In a brief summary, mutations are just like GraphQL queries, except they modify data. In order to make a mutation, we can define a mutation type just like we did a `Query` type in our schema.

Modify your schema in `schema.js` to look like the following:

```
const { gql } = require('apollo-server-express');
const schema = gql`
  type Query {
    getUsers(id:Int, username:String, email:String, password:String): User
  }
  type Mutation {
    createUser(username:String, email:String, password:String): User
  }
  type User {
    id: Int!
    username: String!
    email: String!
    password: String!
  }
`;
```

As you can see, mutations don’t look very different from queries. Of course, you can always get more advanced; these mutations are on a very basic level.

In the `Mutation` type above, we define a `createUser` mutation. This mutation takes in 3 parameters: `username`, `email`, and `password`. The reason we’re not going to provide the `id` property is because we want the `id` to be defined by the computer, whether randomly or in order, not manually.

In order to put our mutation into effect, we’ll need to make some edits to our resolvers. Look at the new resolvers below:

```
let users = [
  {
    id:1,
    username:'The Javascript Ninja',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
  {
    id:2,
    username:'The Javascript Ninjas Best Friend',
    email:'contact@thejavascriptninja.com',
    password:'its-a-secret'
  },
];
const resolvers = {
  Query: {
    getUsers: (parent, args) => {
      if (args.id) {
        return users.filter(user => user.id === args.id);
      } else if (args.username) {
        return users.filter(user => user.username === args.username);
      } else if (args.email) {
        return users.filter(user => user.email === args.email);
      } else if (args.password) {
        return users.filter(user => user.password === args.password);
      } else {
        return users;
      }
    }
  },
  Mutation: {
    createUser: (parent, args) => {
      let newUser = {
        id: users.length + 1,
        username: args.username,
        email: args.email,
        password: args.password
      };
      users.push(newUser);
      return newUser;
    }
  }
}
```

As you can see, in our resolver, we have a new property after the `Query` property! This is the `Mutation` property. In the `Mutation` property, we have the `createUser` method. This is so far our first mutation. In the `createUser` method we do 3 things:

**1.** Create a `newUser` object. In this object, we set the `id`, `username`, `email`, and `password` of our new user.

2. Add the `newUser` object to the database. In reality, we would add the `newUser` to the database. However, since we’re just using a dummy database model, we just use `array.push()` to add the `newUser` to our `users` array.

3. Return the `newUser`. This is pretty straightforward. We just return the `newUser` object as a result of the mutation.

#Running our First Mutation

Now that we’ve got our mutation all done, it’s time to run. (Yes, that rhymes 😀). In order to run our mutation, start your server and navigate to `localhost:3000/graphql`.

![img](https://i1.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-10-at-8.25.47-PM-2.png?resize=768%2C329&ssl=1)

To make sure everything is working right, let’s first run our query. Enter this query into the box on the left:

```
query {
  getUsers {
    id
    username
    email
    password
  }
}
```

You should see the following result:

![img](https://i2.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-18-at-8.58.43-PM.png?resize=768%2C330&ssl=1)

Now that we’ve ensured everything works and we aren’t getting any errors, it’s time to test our mutation. Let’s enter the mutation we wrote earlier:

```
mutation myMutation {
  createUser(username:"Subscriber to TJN", email:"contact@thejavascriptninja.com", password:"secret") {
    id
    username
    email
    password
  }
}
```

As you can see, we call `createUser`, and give it the specified params. It should return the following result:

```
{
  "data": {
    "createUser": {
      "id": 3,
      "username": "Subscriber to TJN",
      "email": "contact@thejavascriptninja.com",
      "password": "secret"
    }
  }
}
```
![img](https://i2.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-18-at-9.09.14-PM.png?resize=768%2C330&ssl=1)

Then, if we run our query again, we can see our mutation has taken effect.

Run:

```
query {
  getUsers {
    id
    username
    email
    password
  }
}
```

You should see the following:

```
{
  "data": {
    "getUsers": [
      {
        "id": 1,
        "username": "The Javascript Ninja",
        "email": "contact@thejavascriptninja.com",
        "password": "its-a-secret"
      },
      {
        "id": 2,
        "username": "The Javascript Ninjas Best Friend",
        "email": "contact@thejavascriptninja.com",
        "password": "its-a-secret"
      },
      {
        "id": 3,
        "username": "Subscriber to TJN",
        "email": "contact@thejavascriptninja.com",
        "password": "secret"
      }
    ]
  }
}
```
![img](https://i2.wp.com/thejavascriptninja.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-18-at-9.11.41-PM.png?resize=768%2C328&ssl=1)

Hooray! Our mutation worked!

#To Conclude…

A’ight folks!

Today we’ve talked about organizing our code, writing more advanced queries (using parameters and variables), and GraphQL mutations.

Pretty awesome stuff.

I am going to end the tutorial here so it doesn’t get too long, but make sure to [subscribe](thejavascriptninja.com) so you don’t miss out on any great content!

Stay tuned and talk soon!