GraphQL Server Using NEXT.js and MongoDB Atlas
Setup
yarn install
Create ur own MONGODB_URI
into .env file (.env.development or .env.local) and add ur mongodb uri.
Ready
Modify all u need to ur project
Development mode
yarn dev
First, sorry if something is not well written, I am still learning English
yarn add [email protected] mongoose graphql
I used this version of apollo-server-micro because the new version 3 sends you to a sandbox that in my opinion is uncomfortable.
In the root of your project create a folder with the name you prefer, in this case I use "db". Inside create two more folders, one called "config" and the other "models"
mkdir db && cd db && mkdir config && mkdir models
Inside the config folder create an index.js file and add "moongose". For the MongoDb uri it is good practice to add it inside an .env file and bring it with proccess.env.
const mongoose = require('mongoose')
const MongoDb = process.env.MONGODB_URI
const connectDb = async () => {
try {
await mongoose.connect(MongoDb, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
})
console.log('db success connect')
} catch (err) {
console.log('error connecting to database')
console.log(err)
process.exit(1)
}
}
module.exports = connectDb
Now we are going to create an example model, in this case the product model. So inside the "models" folder I create a file called product.js and add moongose and what I need for the model.
import mongoose from 'mongoose'
const { Schema } = mongoose
mongoose.Promise = global.Promise
const ProductsSchema = new Schema({
name: {
type: String,
required: true,
trim: true,
},
productionCapacity: {
type: Number,
required: true,
trim: true,
},
price: {
type: Number,
required: true,
trim: true,
},
description: {
type: String,
trim: true,
},
createAt: {
type: Date,
defalut: Date.now(),
},
})
ProductsSchema.index({ name: 'text' })
module.exports =
mongoose.models.Product || mongoose.model('Product', ProductsSchema)
I'll leave the code here as an example because your project can be totally different.
For the schema we will import gql
from apollo-server-micro
and create a constant called "typeDefs" in which we will use gql
and inside we will define our types, inputs, queries and mutations
import { gql } from 'apollo-server-micro'
const typeDefs = gql`
# Products
type Product {
id: ID
name: String
productionCapacity: Int
price: Float
description: String
}
input ProductInput {
name: String!
productionCapacity: Int!
price: Float!
description: String
}
type Query {
getProducts: [Product]
getProduct(id: ID!): Product
}
type Mutation {
#Products
newProduct(input: ProductInput): Product
updateProduct(id: ID!, input: ProductInput): Product
deleteProduct(id: ID!): String
}
`
module.exports = typeDefs
I will leave the code that I use, but remember that your project can be very different. We bring the models, in this case I bring my "product" model to be able to use it within the queries or mutations that I define.
const Product = require('./models/product')
const resolvers = {
Query: {
// products
getProducts: async () => {
try {
const products = await Product.find({})
return products
} catch (err) {
console.log(err)
}
},
getProduct: async (_, { id }) => {
const product = await Product.findById(id)
if (!product) {
throw new Error('Product not found')
}
return product
},
},
Mutation: {
// products
newProduct: async (_, { input }) => {
try {
const product = new Product(input)
const result = await product.save()
return result
} catch (err) {
console.log(err)
}
},
updateProduct: async (_, { id, input }) => {
let product = await Product.findById(id)
if (!product) {
throw new Error('Product not found')
}
product = await Product.findOneAndUpdate({ _id: id }, input, {
new: true,
})
return product
},
deleteProduct: async (_, { id }) => {
const product = await Product.findById(id)
if (!product) {
throw new Error('Producto no encontrado')
}
await Product.findOneAndDelete({ _id: id })
return 'Producto eliminado'
},
},
}
module.exports = resolvers
First we create a graphql.js file (it can be called whatever) inside /pages/api.
In the graphql.js file we are going to import ApolloServer
and makeExecutableSchema
from apollo-server-micro
and typeDefs
, resolvers
and connectDb
from their corresponding files. Then we run the connectDb()
function and create a schema with makeExecutableSchema
which will have the typeDefs
and the resolvers
.
And at the end we export the Apollo Server passing it our schema variable and defining the path that must match the name of the file that we put in /pages/api.
import { ApolloServer, makeExecutableSchema } from 'apollo-server-micro'
import typeDefs from '../../db/schema'
import resolvers from '../../db/resolvers'
import connectDb from '../../db/config'
connectDb()
export const schema = makeExecutableSchema({
typeDefs,
resolvers
})
export const config = {
api: {
bodyParser: false,
},
}
export default new ApolloServer({ schema }).createHandler({
path: '/api/graphql',
})
Your project should have been more or less like this
Now run the project and go to the url of your api with graphql
yarn dev
I leave the package.json for you to check the version of the dependencies used in this post.
{
"name": "graphql-nextjs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"apollo-server-micro": "2.25.1",
"graphql": "^15.5.1",
"mongoose": "^5.13.5",
"next": "11.0.1",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"eslint": "7.32.0",
"eslint-config-next": "11.0.1"
}
}
yarn install
Create ur own MONGODB_URI
into .env file (.env.development or .env.local) and add ur mongodb uri.
Modify all u need to ur project
yarn dev