Mutations and input types

 

Let’s scrap our user greeting and make really useful schema, that will show up a dog breed catalog. We are going to use it in another tutorial to create a React component to display the dog catalog.

Set up mock data.

Create a file under ./src/modules/mock_data that will serve as our data provider. Let’s add a couple of dog breeds there.

./src/modules/mock_data/dogs.js

module.exports = [
  {
    "breed": "affenpinscher",
    "displayImage": "https://images.dog.ceo/breeds/affenpinscher/n02110627_10225.jpg",
    "id": "Z1fdFgU"
  },
  {
    "breed": "african",
    "displayImage": "https://images.dog.ceo/breeds/african/n02116738_2515.jpg",
    "id": "Z1gPiBt"
  },
  {
    "breed": "airedale",
    "displayImage": "https://images.dog.ceo/breeds/airedale/n02096051_6335.jpg",
    "id": "ZNDtCU"
  },
  {
    "breed": "akita",
    "displayImage": "https://images.dog.ceo/breeds/akita/Japaneseakita.jpg",
    "id": "6HalQ"
  },
  {
    "breed": "appenzeller",
    "displayImage": "https://images.dog.ceo/breeds/appenzeller/n02107908_3311.jpg",
    "id": "Z1tlucN"
  },
  {
    "breed": "basenji",
    "displayImage": "https://images.dog.ceo/breeds/basenji/n02110806_3415.jpg",
    "id": "Zo1k5y"
  }  
];

Writing a query to fetch the mock data.

Let’s first write a query to fetch dog’s details based on the breed.

Based on the JSON data above, dog’s schema would look like this:

...
  type dog {
    id: String,
    breed: String,
    displayImage: String
  }
  type dogsCatalog {
    getDogByBreed(breed: String): dog
  }
  type Query {
    queryDogs: dogsCatalog
  } 
...

We created a dogCatalog query (line 7) that accepts the dog breed, and returns a dog type declared in the beginning of the sniped above.

Then the resolver would look like this:

...
class dogsCatalog {
  
  getDogByBreed({breed}) {
    var result = dogs.find(function(dog){
      return breed == dog.breed ? dog : null;
    });
    return result;
  }
}
...

 

Write the mutation.

The mutations are used to modify data. In GraphQL they are similar as queries and could be written in a similar way.

The basic idea.

...
  type Mutation {
    setNewDog(id: String, breed: String, displayImage: String): String
  }  
...

here, we defined mutation named setNewDog which simply takes a few parameters (id, breed and displayImage) and returns the status message.

The resolver will look like this:

...
  setNewDog: ({id, breed, displayImage}) => {
    var result = dogs.find(function(dog){
      return breed == dog.breed ? dog : null;
    });
    if(result != null) {
      return 'dog allready exists!';
    }

    dogs.push({
      "breed": breed,
      "displayImage": displayImage,
      "id": id      
    });
    return 'dog added successfuly !';
  }
...

Let’s put them all together:

./src/server.js

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
var dogs = require('./src/models/mock_data/dogs.js');

// Construct a schema, using GraphQL schema language

var schema = buildSchema(`


  type Mutation {
    setNewDog(id: String, breed: String, displayImage: String): String
  }  

  type dog {
    id: String,
    breed: String,
    displayImage: String
  }

  type dogsCatalog {
    getDogByBreed(breed: String): dog
  }

  type Query {
    queryDogs: dogsCatalog
  }  
`);

class dogsCatalog {
  
  getDogByBreed({breed}) {
    var result = dogs.find(function(dog){
      return breed == dog.breed ? dog : null;
    });
    return result;
  }
}

// The root provides a resolver function for each API endpoint
var root = {
  queryDogs: () => {
    return new dogsCatalog();
  },
  setNewDog: ({id, breed, displayImage}) => {
    var result = dogs.find(function(dog){
      return breed == dog.breed ? dog : null;
    });
    if(result != null) {
      return 'dog already exists!';
    }

    dogs.push({
      "breed": breed,
      "displayImage": displayImage,
      "id": id      
    });
    return 'dog added successfully !';
  }
};

var app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

Test Using GraphQL UI

Writing a query to fetch existing data.

Now navigate to GraphQL UI http://localhost:4001/graphql and add this in the query window (up left)

query queryLabel($breed: String!) {
  queryDogs {
    getDogByBreed(breed: $breed) {
      id
      displayImage,
      breed
    }
  }
}

and this in the variables window (down left)

{
  "breed": "african"
}

hit play and the result should be this:

{
  "data": {
    "queryDogs": {
      "getDogByBreed": {
        "id": "Z1gPiBt",
        "displayImage": "https://images.dog.ceo/breeds/african/n02116738_2515.jpg",
        "breed": "african"
      }
    }
  }
}

Now change the breed in the variables window (down left) to ‘labrador’ and hit play again, and the result is null since there is no record for this breed.

Write a mutation to add a new record to data structure.

Open a new QraphQL UI tab and add the following mutation in the query window:

mutation setNewDogLabel($id: String, $breed: String, $displayImage: String) {
  setNewDog(id: $id, breed: $breed, displayImage: $displayImage)
}

and this in the variables window:

{
  "id": "Z2iEkxg",
  "breed": "labrador",
  "displayImage": "https://images.dog.ceo/breeds/labrador/n02099712_2120.jpg"
}

Hit play and if everything went well you will see the success message.

{
  "data": {
    "setNewDog": "dog added successfuly !"
  }
}

(Out of curiosity you might want to hit play one more time to see what message you will get)

Now, navigate back to the previous GraphQL UI tab and hit play again and you will see newly created record.

 

 

 

 

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
var dogs = require('./src/models/mock_data/dogs.js');

// Construct a schema, using GraphQL schema language

var schema = buildSchema(`

  input DogInput {
    id: String,
    breed: String,
    displayImage: String
  }

  type Mutation {
    setNewDog(input: DogInput): String
  }  

  type dog {
    id: String,
    breed: String,
    displayImage: String
  }

  type dogsCatalog {
    getDogByBreed(breed: String): dog
  }

  type Query {
    queryDogs: dogsCatalog
  }  
`);

class dogsCatalog {
  
  getDogByBreed({breed}) {
    var result = dogs.find(function(dog){
      return breed == dog.breed ? dog : null;
    });
    return result;
  }
}

// The root provides a resolver function for each API endpoint
var root = {
  queryDogs: () => {
    return new dogsCatalog();
  },
  setNewDog: ({input}) => {
    var result = dogs.find(function(dog){
      return input.breed == dog.breed ? dog : null;
    });
    if(result != null) {
      return 'dog allready exists!';
    }

    dogs.push({
      "breed": input.breed,
      "displayImage": input.displayImage,
      "id": input.id      
    });
    return 'dog added successfuly !';
  }
};

var app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

 

Leave a Reply