├── .gitignore ├── .babelrc ├── readme └── runtheapp.gif ├── src ├── models │ └── user │ │ ├── userType.js │ │ ├── userQueries.js │ │ ├── userMutations.js │ │ └── userSchema.js └── index.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /readme/runtheapp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/applification/graphql-express-mongodb/HEAD/readme/runtheapp.gif -------------------------------------------------------------------------------- /src/models/user/userType.js: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLObjectType, 3 | GraphQLSchema, 4 | GraphQLString, 5 | GraphQLInt, 6 | GraphQLNonNull, 7 | GraphQLList, 8 | GraphQLID 9 | } from 'graphql' 10 | 11 | // Define our user type, with two string fields; `id` and `name` 12 | export default new GraphQLObjectType({ 13 | name: 'User', 14 | description: 'User object', 15 | fields: () => ({ 16 | _id: { 17 | type: new GraphQLNonNull(GraphQLID) 18 | }, 19 | id: { 20 | type: GraphQLString 21 | }, 22 | name: { 23 | type: new GraphQLNonNull(GraphQLString) 24 | }, 25 | email:{ 26 | type: GraphQLString 27 | }, 28 | tel: { 29 | type: GraphQLString 30 | } 31 | }) 32 | }); 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-graphql-test", 3 | "version": "1.0.0", 4 | "description": "GraphQL, Mongo & Express Project", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "dev": "nodemon --exec babel-node src/index.js", 8 | "prestart": "babel src --out-dir dist", 9 | "start": " node dist/index.js" 10 | }, 11 | "author": "Dave Hudson (http://applification.net)", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.13.4", 15 | "express-graphql": "^0.4.9", 16 | "graphql": "^0.4.18", 17 | "mongoose": "^4.4.6" 18 | }, 19 | "devDependencies": { 20 | "babel-cli": "^6.6.5", 21 | "babel-preset-es2015": "^6.6.0", 22 | "nodemon": "^1.9.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/models/user/userQueries.js: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLObjectType, 3 | GraphQLSchema, 4 | GraphQLString, 5 | GraphQLInt, 6 | GraphQLNonNull, 7 | GraphQLList, 8 | GraphQLID 9 | } from 'graphql'; 10 | 11 | import userType from './userType' 12 | import user from './userSchema' 13 | 14 | export default { 15 | users: { 16 | type: new GraphQLList(userType), 17 | resolve: user.getListOfUsers 18 | }, 19 | user: { 20 | type: userType, 21 | args: { 22 | id: { 23 | type: GraphQLID 24 | } 25 | }, 26 | resolve: user.getUserByPosition 27 | }, 28 | userId: { 29 | type: userType, 30 | args: { 31 | id: { 32 | type: GraphQLID 33 | } 34 | }, 35 | resolve: user.getUserById 36 | }, 37 | userByName: { 38 | type: userType, 39 | args: { 40 | name: { 41 | type: GraphQLString 42 | } 43 | }, 44 | resolve: user.getUserByName 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/models/user/userMutations.js: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLObjectType, 3 | GraphQLSchema, 4 | GraphQLString, 5 | GraphQLInt, 6 | GraphQLNonNull, 7 | GraphQLList, 8 | GraphQLID 9 | } from 'graphql'; 10 | 11 | import userType from './userType'; 12 | import user from './userSchema'; 13 | 14 | export default { 15 | addUser:{ 16 | type:userType, 17 | args: { 18 | name:{ 19 | name:'name', 20 | type:new GraphQLNonNull(GraphQLString) 21 | }, 22 | email:{ 23 | name:'email', 24 | type: new GraphQLNonNull(GraphQLString) 25 | }, 26 | tel: { 27 | name:'tel', 28 | type: new GraphQLNonNull(GraphQLString) 29 | } 30 | }, 31 | resolve: user.addUser 32 | }, 33 | updateUser:{ 34 | type:userType, 35 | args: { 36 | id:{ 37 | type: GraphQLID 38 | }, 39 | name:{ 40 | name:'name', 41 | type:new GraphQLNonNull(GraphQLString) 42 | }, 43 | email:{ 44 | name:'email', 45 | type: new GraphQLNonNull(GraphQLString) 46 | }, 47 | tel: { 48 | name:'tel', 49 | type: new GraphQLNonNull(GraphQLString) 50 | } 51 | }, 52 | resolve: user.updateUser 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Import GraphQL and destructure for easy access 2 | import { 3 | GraphQLObjectType, 4 | GraphQLSchema 5 | } from 'graphql' 6 | 7 | // Import express server 8 | import express from 'express' 9 | 10 | // Import mongoose to connect to MongoDB 11 | import mongoose from 'mongoose' 12 | 13 | // Import express-graphql an easy express integration of https://github.com/graphql/graphiql 14 | import graphqlHTTP from 'express-graphql' 15 | 16 | // Import GraphQL Queries 17 | import userQueries from './models/user/userQueries' 18 | 19 | // Import GraphQL Mutations 20 | import userMutations from './models/user/userMutations' 21 | 22 | // Setup GraphQL RootQuery 23 | let RootQuery = new GraphQLObjectType({ 24 | name: 'Query', 25 | description: 'Realize Root Query', 26 | fields: () => ({ 27 | user: userQueries.user, 28 | users: userQueries.users, 29 | userId: userQueries.userId, 30 | userByName: userQueries.userByName 31 | }) 32 | }) 33 | 34 | // Setup GraphQL RootMutation 35 | let RootMutation = new GraphQLObjectType({ 36 | name: 'Mutation', 37 | description: 'Realize Root Mutations', 38 | fields: () => ({ 39 | addUser: userMutations.addUser, 40 | updateUser: userMutations.updateUser 41 | }) 42 | }) 43 | 44 | // Set up GraphQL Schema with our RootQuery and RootMutation 45 | let schema = new GraphQLSchema({ 46 | query: RootQuery, 47 | mutation: RootMutation 48 | }) 49 | 50 | // Connect MongoDB with Mongoose 51 | mongoose.connect('mongodb://localhost/graphql-express-mongodb') 52 | 53 | // Set up Express and integrate with our GraphQL Schema and configure to use graphiql 54 | var app = express() 55 | app.use('/graphql', graphqlHTTP({ schema: schema, graphiql: true })) 56 | app.listen('3000') 57 | 58 | var status = { 59 | Express: { 60 | "Online": true, 61 | "Port": 3000 62 | }, 63 | "GraphiQL": { 64 | "url": "http://localhost:3000/graphql" 65 | } 66 | } 67 | console.dir(status, {depth: null, colors: true }) 68 | -------------------------------------------------------------------------------- /src/models/user/userSchema.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | var userSchema = new mongoose.Schema({ 4 | id: { type:String, required:true, unique:true, index:true, default:mongoose.Types.ObjectId }, 5 | name: String, 6 | email: String, 7 | tel: String, 8 | type: String 9 | }); 10 | 11 | let user = mongoose.model('user', userSchema); 12 | 13 | module.exports = user; 14 | 15 | module.exports.getListOfUsers = () => { 16 | return new Promise((resolve, reject) => { 17 | user.find({}).exec((err, res) => { 18 | err ? reject(err) : resolve(res); 19 | }); 20 | }); 21 | }; 22 | 23 | module.exports.getUserById = (root, {id}) => { 24 | return new Promise((resolve, reject) => { 25 | user.findOne({ 26 | id: id 27 | }).exec((err, res) => { 28 | err ? reject(err) : resolve(res); 29 | }); 30 | }); 31 | }; 32 | 33 | module.exports.getUserByName = (root, {name}) => { 34 | return new Promise((resolve, reject) => { 35 | user.findOne({ 36 | name: name 37 | }).exec((err, res) => { 38 | err ? reject(err) : resolve(res); 39 | }); 40 | }); 41 | }; 42 | 43 | module.exports.getUserByPosition = (root, {id}) => { 44 | return new Promise((resolve, reject) => { 45 | user.find({}).exec((err, res) => { 46 | err ? reject(err) : resolve(res[id]); 47 | }); 48 | }); 49 | }; 50 | 51 | module.exports.addUser = (root, {name, email, tel}) => { 52 | var newUser = new user({name:name, email:email, tel:tel}); 53 | 54 | return new Promise((resolve, reject) => { 55 | newUser.save((err, res) => { 56 | err ? reject(err): resolve(res); 57 | }); 58 | }); 59 | } 60 | 61 | module.exports.updateUser = (root, {id, name, email, tel}) => { 62 | var updateUser = {name:name, email:email, tel:tel}; 63 | return new Promise((resolve, reject) => { 64 | user.findOneAndUpdate( 65 | { id: id }, 66 | { $set: updateUser }, 67 | { returnNewDocument: true } 68 | ).exec((err, res) => { 69 | err ? reject(err) : resolve(res); 70 | }); 71 | }); 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraphQL + Express + MongoDB 2 | 3 | > A small project to illustrate using GraphQL with MongoDB in Express as simply as possible 4 | 5 | #### Project Goals: 6 | * Create a GraphQL + MongoDB + Express project that is as __simple as possible__ 7 | * __GraphiQL Integration__ to send Queries / Mutations 8 | * Ability to use __Postman or other REST Client__ to POST GraphQL Queries / Mutations 9 | * Use of __ES6__ (but minimally) 10 | * Full Create, Update and Query from GraphQL to MongoDB 11 | 12 | ## Installation 13 | 14 | #### ES6 / Node V4+ 15 | This project makes use of ES6 which requires a 4+ version of Node https://nodejs.org/en/download/ 16 | 17 | #### MongoDB 18 | In order to run this project you need to install MongoDB and ensure an instance is running. 19 | https://www.npmjs.com/package/mongodb 20 | 21 | ```js 22 | npm install mongodb --save 23 | mongod 24 | ``` 25 | 26 | To see the data you are saving you can use a MongoDB Manager App such as https://robomongo.org/ 27 | 28 | #### NPM Modules 29 | The following NPM modules are required in package.json: 30 | 31 | * express 32 | * express-graphql 33 | * graphql 34 | * mongoose 35 | * babel-cli 36 | * babel-preset-es2015 37 | * nodemon 38 | 39 | Install with: 40 | 41 | ```js 42 | npm install 43 | ``` 44 | 45 | #### Run the project 46 | 47 | ##### Running in Development 48 | npm dev is configured with nodmon so that the server automatically restarts when code files are changes 49 | ```js 50 | npm run dev 51 | ``` 52 | 53 | ##### Running in Production 54 | ```js 55 | npm start 56 | ``` 57 | npm prestart will run first, transpile the ES6 code and save to _dist_ folder. npm start will then run the code directly from the _dist_ folder 58 | 59 | ![CLI Commands](https://raw.githubusercontent.com/applification/graphql-express-mongodb/master/readme/runtheapp.gif) 60 | 61 | ## Running GraphQL Mutations & Queries 62 | You can run these queries / mutations within GraphiQL, alternatively you can run them within a tool such as Postman. To do so ensure you POST the query / mutation in the body and set the content-type to GraphQL. 63 | 64 | #### Create a user 65 | ```js 66 | mutation { 67 | addUser( name:"Jeff Beck", email:"jeff@beck.net", tel:"0800") { 68 | id, 69 | name, 70 | email, 71 | tel 72 | } 73 | } 74 | ``` 75 | 76 | #### Find a user 77 | Find the first user in the MongoDB, requesting just the name and email address 78 | ```js 79 | query { 80 | userId(id:"56e0582a07be7df61583d9a4") { 81 | name, 82 | email 83 | } 84 | } 85 | ``` 86 | #### Show all users 87 | ```js 88 | query { 89 | users { 90 | id, 91 | name, 92 | email 93 | } 94 | } 95 | ``` 96 | 97 | #### Update a user 98 | ```js 99 | mutation { 100 | updateUser(id:"56e0919c2c4670ed23fe4a28", name:"Jeff The Beck", email:"jeff@beck.net", tel:"0800 234 231") { 101 | id 102 | } 103 | } 104 | ``` 105 | 106 | ## GraphQL Resolvers 107 | GraphQL doesn't care where your data is stored, in this case it's in a MongoDB. 108 | 109 | [userSchema.js](src/models/user/userSchema.js) uses a Mongoose Schemea and configures a number of exported functions for our GraphQL Resolvers to work with in order to load a user / list of users or create and update a user. 110 | 111 | ## GraphQL Schema 112 | [userType.js](src/models/user/userType.js) creates a GraphQLObjectType describing the structure of our data model. 113 | 114 | [userMutations.js](src/models/user/userMutations.js) and [userQueries.js](src/models/user/userQueries.js) specify the operations available from GraphQL and link to our resolvers, in this case Mongoose operations that return a promise. 115 | --------------------------------------------------------------------------------