Today we will start second part of this article series for creating mern app using graphql. In part-1, we have made progress upto extracting data from our queries, now we will proceed further on this.
GitHub Link : MERN-app-using-graphql-apollo-client
MERN App using GraphQL via Apollo-Client,(React Hooks). (Part-1)
vinodchauhan7 ・ Sep 10 '19 ・ 8 min read
Now we first define the relations between the Car and owner. And how details can be fetched.
a) Type Relations
1) At first, We give 'ownerId' to each car.
2) Define the relations of car with unique owner in 'CarType'.
3) Define the list of cars with each Owner with ownerId in Owner Type.
4) Cars and Owners Query in rootQuery.
//Schema.js
const graphql = require("graphql"); //use graphql package
const _ = require("lodash");
/*Getting GraphQLObjectType function from 'graphql' to define the (dataType)
structure of our queries and their model type.
*/
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLInt,
GraphQLSchema,
GraphQLList
} = graphql;
const CarsArray = [
{ id: "1", name: "S-Class", model: "2019", company: "Mercedes" ,ownerId : "1"},
{ id: "2", name: "Continental GT", model: "2019", company: "Bentley",ownerId : "2" },
{ id: "3", name: "Phantom", model: "2019", company: "Rolls-Royce",ownerId : "1" },
{ id: "4", name: "Panamera", model: "2019", company: "Porsche" ,ownerId : "2"},
{ id: "5", name: "A8", model: "2019", company: "Audi" ,ownerId : "1"},
{ id: "6", name: "I-Pace", model: "2019", company: "Jaguar",ownerId : "3"}
];
var OwnersArray = [
{ id: "1", name: "Vinod Chauhan", age: 27, gender: "male" },
{ id: "2", name: "John Dow", age: 46, gender: "male" },
{ id: "3", name: "Kristen", age: 30, gender: "female" },
{ id: "4", name: "Paris", age: 44, gender: "female" },
{ id: "5", name: "Sylvestor", age: 26, gender: "male" }
];
//Defining CarType with its fields.
const CarType = new GraphQLObjectType({
name: "Car",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
model: { type: GraphQLInt },
company: { type: GraphQLString },
owner : { //Supporting pwner query in carType
type: OwnerType,
resolve(parent,args){
return _.find(OwnersArray,{id:parent.ownerId});
}
}//owner
})
});
//Defining CarType with its fields.
const OwnerType = new GraphQLObjectType({
name: "Owner",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
gender: { type: GraphQLString },
cars : { // Supporting list of cars query in Owner type
type : new GraphQLList(CarType),
resolve(parent,args){
return _.filter(CarsArray,{ownerId : parent.id});
}
}
})
});
//Defining RootQuery
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
// Fields here will be the query for frontends
//We are defining a 'car' query which can take (car ID ) to search in DB.
car: {
type: CarType, //Defining model for car Query
args: { id: { type: GraphQLID } }, //args field to extract
// argument came with car query, e.g : Id of the car object to extract its details.
resolve(parent, args) {
//code to get value from DB
/**
* With the help of lodash library(_), we are trying to find car with id from 'CarsArray'
* and returning its required data to calling tool.
*/
return _.find(CarsArray, { id: args.id });
} //resolve function
}, //car query ends here
owner: {
type: OwnerType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return _.find(OwnersArray, { id: args.id });
}
},//owners ends here
cars : {
type : new GraphQLList(CarType),
resolve(parent,args){
return CarsArray;
}
},//cars query
owners : {
type : new GraphQLList(OwnerType),
resolve(parent,args){
return OwnersArray;
}
}
} //fields end here
});
//exporting 'GraphQLSchema with RootQuery' for GraphqlHTTP middleware.
module.exports = new GraphQLSchema({
query: RootQuery
});
You can see result like this.
Hope you all got understanding of graphql upto this point and now we will connect with mongoDB(Database).
For Database, we will use online mongoDB server mlab www.mlab.com. Those who don't know what is mlab and how to create database & credentials on it, then please look for any youtube video you will get your all answers.
b) Database Connectivity
To connect with mlab server(mongoDB) we will use mongoose package.
//In app.js
//Get the express library from node_modules which we have just downloaded.
const express = require("express");
const graphqlHTTP = require("express-graphql");
const mongoose = require("mongoose"); //using mongoose to connect with db
//Imports
const schema = require("./schema/schema");
//Making const of express() into a variable (JS function first class Object).
const app = express();
//Please change mongoDB connection as maybe I have deleted this db on mlab when you are using it.
mongoose.connect(
"mongodb://test:test123@ds145434.mlab.com:45434/gql-practice",
{ useNewUrlParser: true },
() => {
console.log("Connect with DB successfully.");
}
);
/*We can use graphql on express server with middlewares, so that whenever
we need graphql query from frontend, our express server can handle it
smoothly.
*/
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
graphiql: true
})
);
//When our application starts, it will listen on port 4000
app.listen(4000, () => {
console.log("Server is listening on port 4000");
});
Output on terminal
//Output on console
[nodemon] restarting due to changes...
[nodemon] starting `node .\app.js`
Server is listening on port 4000
Connect with DB successfully
C) Creating models for mongoDB.
Here we need to create models of carType and OwnerType which mongoDB can understand, which enables us to save our record in it.
1) Create 'models' folder inside 'server' folder.
2) Create file 'Car' model to store different car details.
3) Create file 'Owner' model to store differet owner details.
//car.js
const mongoose = require("mongoose");
const CarSchema = new mongoose.Schema({
name: String,
model: Number,
company: String,
ownerId: String
});
module.exports = mongoose.model("cars", CarSchema);
//---------------------------------------------------------
//owner.js
const mongoose = require("mongoose");
const ownerSchema = new mongoose.Schema({
name: String,
age: Number,
gender: String
});
module.exports = mongoose.model("owners", ownerSchema);
d) Understanding CRUD 'MUTATIONS' in GraphQL.
To implement crud implementation in graphql we need to understand mutations in it.
Mutation is an object type of GraphQLObjectType() in which we can add different operations like addCar, addOwner & so on.
//schema.js
const graphql = require("graphql"); //use graphql package
const _ = require("lodash");
const cars = require("../models/car");
const owners = require("../models/owner");
/*Getting GraphQLObjectType function from 'graphql' to define the (dataType)
structure of our queries and their model type.
*/
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLInt,
GraphQLSchema,
GraphQLList
} = graphql;
//Defining CarType with its fields.
const CarType = new GraphQLObjectType({
name: "Car",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
model: { type: GraphQLInt },
company: { type: GraphQLString },
owner: {
type: OwnerType,
resolve(parent, args) {
// return _.find(OwnersArray, { id: parent.ownerId });
}
} //owner
})
});
//Defining CarType with its fields.
const OwnerType = new GraphQLObjectType({
name: "Owner",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
gender: { type: GraphQLString },
cars: {
type: new GraphQLList(CarType),
resolve(parent, args) {
//return _.filter(CarsArray, { ownerId: parent.id });
}
}
})
});
//Defining RootQuery
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
// Fields here will be the query for frontends
//We are defining a 'car' query which can take (car ID ) to search in DB.
car: {
type: CarType, //Defining model for car Query
args: { id: { type: GraphQLID } }, //args field to extract
// argument came with car query, e.g : Id of the car object to extract its details.
resolve(parent, args) {
//code to get value from DB
/**
* With the help of lodash library(_), we are trying to find car with id from 'CarsArray'
* and returning its required data to calling tool.
*/
//return _.find(CarsArray, { id: args.id });
} //resolve function
}, //car query ends here
owner: {
type: OwnerType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
// return _.find(OwnersArray, { id: args.id });
}
}, //owners ends here
cars: {
type: new GraphQLList(CarType),
resolve(parent, args) {
//return CarsArray;
}
}, //cars query
owners: {
type: new GraphQLList(OwnerType),
resolve(parent, args) {
//return OwnersArray;
}
}
} //fields end here
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addOwner: { // To add Owner in DB
type: OwnerType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt },
gender: { type: GraphQLString }
},
resolve(parent, args) {
let owner = new owners({
name: args.name,
age: args.age,
gender: args.gender
});
return owner.save(); //create owner data in mlab
}
}
} //fields ends here
});
//exporting 'GraphQLSchema with RootQuery' for GraphqlHTTP middleware.
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
In above screenshot, we have done following steps to connect our graphQL-Express server with mongoDb :
1) Import cars & owners model in it.
2) Remove dummy Data.
3) Comment out all returns as we will get data from db now.
4) Create a new Object mutations(means to mutate something) to implement our crud logic.
5) Add entry of Mutation object in GraphQLSchema.
Open localhost:4000/graphql, Here on the right side you will new entry mutation.
Similarly do above steps for adding 'addCar' after 'addOwner' mutation.
addCar: {
type: CarType,
args: {
name: { type: GraphQLString },
model: { type: GraphQLInt },
company: { type: GraphQLString },
ownerId: { type: GraphQLID }
},
resolve(parent, args) {
let car = new cars({
name: args.name,
model: args.model,
company: args.company,
ownerId: args.ownerId
});
return car.save();
}
}//addCar
e) Update Resolve function for all queries
const graphql = require("graphql"); //use graphql package
const _ = require("lodash");
const cars = require("../models/car");
const owners = require("../models/owner");
/*Getting GraphQLObjectType function from 'graphql' to define the (dataType)
structure of our queries and their model type.
*/
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLInt,
GraphQLSchema,
GraphQLList
} = graphql;
//Defining CarType with its fields.
const CarType = new GraphQLObjectType({
name: "Car",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
model: { type: GraphQLInt },
company: { type: GraphQLString },
owner: {
type: OwnerType,
resolve(parent, args) {
return owners.findById(parent.ownerId);
}
} //owner
})
});
//Defining CarType with its fields.
const OwnerType = new GraphQLObjectType({
name: "Owner",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
gender: { type: GraphQLString },
cars: {
type: new GraphQLList(CarType),
resolve(parent, args) {
return cars.find({ ownerId: parent.id });
}
}
})
});
//Defining RootQuery
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
// Fields here will be the query for frontends
//We are defining a 'car' query which can take (car ID ) to search in DB.
car: {
type: CarType, //Defining model for car Query
args: { id: { type: GraphQLID } }, //args field to extract
// argument came with car query, e.g : Id of the car object to extract its details.
resolve(parent, args) {
//code to get value from DB
/**
* With the help of lodash library(_), we are trying to find car with id from 'CarsArray'
* and returning its required data to calling tool.
*/
return cars.findById(args.id);
} //resolve function
}, //car query ends here
owner: {
type: OwnerType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return owners.findById(args.id);
}
}, //owners ends here
cars: {
type: new GraphQLList(CarType),
resolve(parent, args) {
return cars.find({});
}
}, //cars query
owners: {
type: new GraphQLList(OwnerType),
resolve(parent, args) {
return owners.find({});
}
}
} //fields end here
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addOwner: {
type: OwnerType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt },
gender: { type: GraphQLString }
},
resolve(parent, args) {
let owner = new owners({
name: args.name,
age: args.age,
gender: args.gender
});
return owner.save();
}
}, //AddOwner ends here
addCar: {
type: CarType,
args: {
name: { type: GraphQLString },
model: { type: GraphQLInt },
company: { type: GraphQLString },
ownerId: { type: GraphQLID }
},
resolve(parent, args) {
let car = new cars({
name: args.name,
model: args.model,
company: args.company,
ownerId: args.ownerId
});
return car.save();
}
} //addCar
} //fields ends here
});
//exporting 'GraphQLSchema with RootQuery' for GraphqlHTTP middleware.
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
open localhost:4000/graphql , do your queries on it.
Code Structure
Congratulations!! We have just made our express-graphql server with mongoDB. In next part, we will create frontEnd client(react + apollo-client) to hit this queries. Till then bye guys & have fun.
Top comments (2)
Very good series Vinod.
Your flow was excellent, keep it up
Few suggestions,
That said, you should teach more series 🙌
Thanx Paramanantham for the appreciation, In next articles, I will keep in mind about your suggestions.