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.指令的动态变量名必须是 '$'开头

posted @ 2019-03-21 10:58  蚍蜉搬运工  阅读(249)  评论(0编辑  收藏  举报