Graphql 简单样例
1.1执行 node init
1.2执行 cnpm i --save-dev express exppress-graphql graphql lodash
2.创建server.js 、data.js 和 graphql/schema.js 文件
const express = require('express'); const expressGraphql = require('express-graphql'); const { graphql, buildSchema } = require("graphql"); const app = express(); const schema = require('./graphql/schema'); app.use('/graphql', expressGraphql({ schema, graphiql: true })); app.get('/', (req, res) => res.end('index')); app.listen(8000, (err) => { if (err) { throw new Error(err); } console.log('8000 server started.'); });
4.data.js 代码
var userList = [{ id: 1, name: 'hu.hu', firstName: 'hu', lastName: 'hu', roleId: 1, createDate: "2018-11-15 14:32:43", employee: [2] }, { id: 2, name: 'ko.ko', firstName: 'ko', lastName: 'ko', roleId: 2, createDate: "2018-8-15 14:32:43", leader: 1 }, { id: 3, name: 'RE.fg', firstName: 'RE', lastName: 'fg', roleId: 1, createDate: "2018-7-15 14:32:43", employee: [3] }, { id: 4, name: 'GF.ds', firstName: 'GF', lastName: 'ds', roleId: 2, leader: 3, createDate: "2018-7-12 14:32:43" }, { id: 5, name: 'AS.wd', firstName: 'AS', lastName: 'wd', roleId: 1, createDate: "2018-3-15 14:32:43", employee: [] } ]; module.exports = userList;
5. schema.js 代码
var userData = require("../data"); var _ = require('lodash'); var { GraphQLObjectType, GraphQLInt, GraphQLString, GraphQLEnumType, GraphQLList, GraphQLSchema, GraphQLNonNull, GraphQLScalarType, GraphQLInterfaceType, GraphQLUnionType, GraphQLInputObjectType, } = require('graphql'); let GraphQLDate = new GraphQLScalarType({ name: 'Date', serialize: (value) => { console.log('save:', value); return new Date(value); // value sent to the client }, parseValue: (value) => { console.log('send', value); return new Date(value); // value from the client }, parseLiteral: (ast) => { console.log("ast:", ast); // check type try { if (ast.kind == "StringValue") { return new Date(ast.value); } return null; } catch (err) { return null; } } }); let Role = new GraphQLEnumType({ name: 'Role', values: { "Admin": { value: 1 }, "Normal": { value: 2 } } }); let userModel = new GraphQLInterfaceType({ name: 'UserModel', fields: { id: { type: GraphQLInt }, name: { type: GraphQLString }, firstName: { type: GraphQLString }, lastName: { type: GraphQLString }, roleId: { type: Role }, createDate: { type: GraphQLDate } }, resolveType: (value) => { if (value.employee) { return adminUser; } if (value.leader) { return normalUser; } } }); let adminUser = new GraphQLObjectType({ name: "AdminUser", interfaces: [userModel], fields: { id: { type: GraphQLInt }, name: { type: GraphQLString }, firstName: { type: GraphQLString }, lastName: { type: GraphQLString }, roleId: { type: Role }, createDate: { type: GraphQLDate }, employee: { type: new GraphQLList(GraphQLInt) } }, isTypeOf: (obj) => { return obj.employee; } }); let normalUser = new GraphQLObjectType({ name: "NormalUser", interfaces: [userModel], fields: { id: { type: GraphQLInt }, name: { type: GraphQLString }, firstName: { type: GraphQLString }, lastName: { type: GraphQLString }, roleId: { type: Role }, createDate: { type: GraphQLDate }, leader: { type: GraphQLInt } }, isTypeOf: (obj) => { return obj.leader; } }); let userUnion = new GraphQLUnionType({ name: "UserUnion", types: [adminUser, normalUser], resolveType: (value) => { if (value.employee) { return adminUser; } if (value.leader) { return normalUser; } } }); let userQueryInput = new GraphQLInputObjectType({ name: "UserQueryInput", fields: { id: { type: GraphQLInt }, name: { type: GraphQLString } } }); let userQuery = new GraphQLObjectType({ name: 'UserQuery', fields: { userList: { type: new GraphQLList(userModel), args: { userQuery: { type: userQueryInput } }, resolve: (source, args, context, info) => { let result = (_.filter(userData, (x) => { return args.userQuery && args.userQuery.name ? x.name === args.userQuery.name : true })); return result; } }, user: { type: userUnion, args: { id: { type: new GraphQLNonNull(GraphQLInt) } }, resolve: (source, args, context, info) => { let result = _.first(_.filter(userData, (x) => { return x.id === args.id })); return result; } } } }); let addUserInput = new GraphQLInputObjectType({ name: "AddUserInput", fields: { name: { type: new GraphQLNonNull(GraphQLString) }, firstName: { type: GraphQLString }, lastName: { type: GraphQLString }, roleId: { type: new GraphQLNonNull(GraphQLInt) } } }); let updateUserInput = new GraphQLInputObjectType({ name: "UpdateUserInput", fields: { id: { type: new GraphQLNonNull(GraphQLInt) }, name: { type: new GraphQLNonNull(GraphQLString) }, createDate: { type: GraphQLDate } } }); let userMutation = new GraphQLObjectType({ name: "UserMutation", fields: { addUser: { type: userUnion, args: { addModel: { type: addUserInput } }, resolve: (source, args, context) => { var names = _.split(args.addModel.name, '.'); let newUser = { id: userData.length + 1, name: args.addModel.name, roleId: args.addModel.roleId, firstName: args.addModel.firstName ? args.addModel.firstName : _.first(names), lastName: args.addModel.lastName ? args.addModel.lastName : _.last(names), createDate: new Date(), } if (args.addModel.roleId == 1) { newUser.employee = []; } else { newUser.leader = 1; } userData.push(newUser); return newUser; } }, removeUser: { type: GraphQLInt, args: { id: { type: new GraphQLNonNull(GraphQLInt) } }, resolve: (source, args, context) => { userData = _.filter(userData, (x) => { return x.id != args.id }); return 1; } }, updateUserName: { type: userUnion, args: { updateModel: { type: updateUserInput } }, resolve: (source, args, context) => { let updateUser = _.first(_.filter(userData, (x) => { return x.id == args.updateModel.id })); updateUser.name = args.updateModel.name; var names = _.split(args.updateModel.name, '.'); updateUser.firstName = _.first(names); updateUser.lastName = _.last(names); updateUser.createDate = args.updateModel.createDate ? args.updateModel.createDate : updateUser.createDate; return updateUser; } } } }); module.exports = new GraphQLSchema({ query: userQuery, mutation: userMutation });
6. 执行 node server.js ,启动 8000服务
7.在浏览器中访问localhost:8000/graphql,可以看到如下界面
9.搭建完成
参数解析:
graphql 官网给定了两种方式来实现graphql
1.方式 一
var schema = buildSchema(` type Query { quoteOfTheDay: String random: Float! rollThreeDice: [Int] } `); var root = { quoteOfTheDay: () => { return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; }, random: () => { return Math.random(); }, rollThreeDice: () => { return [1, 2, 3].map(_ => 1 + Math.floor(Math.random() * 6)); }, }; var app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, }));
方式一 是通过buildSchema 来声明 schema,rootValue指定解析函数来实现的。在大多情况下不切合实际开发,因为buildSchema是字符串,不方便发现问题和阅读。
方式二 就是schema.js 代码体现的,通过类型实现和内部指定解析函数的方式。个人认为这个更加合理。
各种类型的参数就不一一解释了,通过跳转到包的定义或者访问官网(http://graphql.cn/graphql-js/basic-types/)查看单词的语义化就可以知道其意思了。
经验:
1.GraphQLInterfaceType 和 GraphQLUnionType 实现时,必须提供 resolveType,负责在查询字段时会报错
2.浏览器中的查询默认是Query,用到mutation时需要指定
3.GraphQLInterfaceType 和 GraphQLUnionType 的数据结构时,在不清楚具体的返回模型类型时,建议编写每个模型的内联
4. query 和 mutation的职责要明确,不要混淆,因为query 里面也可以增删改
5.指令的动态变量名必须是 '$'开头