内容简介:之间折腾过一篇使用springboot构建graphql接口项目的博客传送门这篇博客来折腾一下nodejs中使用express构建graphql接口项目的用法创建文件 server.js 添加下面代码
之间折腾过一篇使用springboot构建graphql接口项目的博客传送门
这篇博客来折腾一下nodejs中使用express构建graphql接口项目的用法
hello world
mkdir graphql-js-demo cd graphql-js-demo npm init yarn add express express-graphql graphql
创建文件 server.js 添加下面代码
const express = require("express");
const graphqlHTTP = require("express-graphql");
// const schema = require("./schema/schema");
var { buildSchema } = require("graphql");
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
hello: String
}
`);
// The root provides a resolver function for each API endpoint
var root = {
hello: () => {
return "Hello world!";
}
};
const app = express();
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
})
);
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
启动
node server.js
浏览器访问 http://localhost:4000/graphql 输入
{
hello
}
点击运行,会得到结果
{
"data": {
"hello": "Hello world!"
}
}
代码来自官网 https://graphql.org/graphql-js/running-an-express-graphql-server/
创建schema
上面只是一个hello world小程序,输出的也是一个静态的字符串,没有涉及到数据的查询,关联等
springboot构建graphql那篇博客里已经说过了graphql的大致运行思路
- 定义schema,也就是数据结构
- 定义查询方法,查询方法里去处理数据的查询以及关联查询等逻辑
定义一个 schema 创建一个文件夹 schema 在这个文件夹里创建一个文件 schema.js 专门用来定义schema和查询方法的
因为要涉及到模拟查询数据,这里要安装一下 lodash
yarn add lodash
const graphql = require("graphql");
const _ = require("lodash");
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLID,
} = graphql;
// 模拟的数据
const books = [
{
id: "1",
name: "java",
},
{
id: "2",
name: "spring",
}
];
// 定义Book的数据结构
const BookType = new GraphQLObjectType({
name: "Book",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
})
});
// 定义查询方法
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return _.find(books, { id: args.id });
}
}
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return books;
}
}
}
});
// 构建schema并导出
module.exports = new GraphQLSchema({
query: RootQuery
});
修改 server.js 内容
const express = require("express");
const graphqlHTTP = require("express-graphql");
const schema = require("./schema/schema");
const app = express();
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
graphiql: true
})
);
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
原接文链: https://tomoya92.github.io/2019/05/31/nodejs-express-graphql-tutorial/
启动服务并查询结果如图
添加关联
有了书本了,现在加上书的作者 Author
关联关系是书本数据中都会有一个 authorId 字段,表示书本关联的 Author 的id,然后在BootType中去定义一个作者的信息,然后处理查询逻辑
const BookType = new GraphQLObjectType({
name: "Book",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
// 定义一个author对象,根据书本中authorId来查询作者的信息
author: {
type: AuthorType,
resolve(parent, args) {
// parent就是当前查询出的book的数据,下面就是从parent中拿到authorId数据再去authors中找作者的信息然后返回,这样数据就组装好了
return _.find(authors, { id: parent.authorId });
}
}
})
});
完整代码如下
const graphql = require("graphql");
const _ = require("lodash");
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLInt,
GraphQLID,
} = graphql;
const books = [
{
id: "1",
name: "java",
authorId: "2"
},
{
id: "2",
name: "spring",
authorId: "3"
},
{
id: "3",
name: "nodejs",
authorId: "1"
},
{
id: "4",
name: "python",
authorId: "2"
},
{
id: "5",
name: "swift",
authorId: "1"
},
{
id: "6",
name: "hibernate",
authorId: "3"
}
];
const authors = [
{
name: "tomcat",
age: 12,
id: "1"
},
{
name: "jetty",
age: 22,
id: "2"
},
{
name: "maven",
age: 21,
id: "3"
}
];
const BookType = new GraphQLObjectType({
name: "Book",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args) {
return _.find(authors, { id: parent.authorId });
}
}
})
});
const AuthorType = new GraphQLObjectType({
name: "Author",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return _.find(books, { id: args.id });
}
}
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return books;
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
启动服务查询结果如图
关联查询
上面实现了查询书本信息顺便查询书本作者的信息,那查询作者顺便把作者下的书本信息也查出来怎么实现呢?
书 关联 作者 是 多对一
相反就是从一的一方查多的一方的数据,跟查书顺便查作者一样,在AuthorType里实现一个查询书的逻辑就可以了
不过一个作者可能有多本书,那么在作者里的书的类型就要是个list了,graphql里提供的有一个 GraphQLList 类型,用法如下
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLInt,
GraphQLID,
GraphQLList
} = graphql;
const AuthorType = new GraphQLObjectType({
name: "Author",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType), // 这里要用new的方式来定义类型,不能直接给books指定成GraphQLList
resolve(parent, args) {
// 同样的 parent 表示 author的信息,下面就是从parent里拿到id再去books数据里找authorId为当前作者的书本数据
return _.filter(books, { authorId: parent.id });
}
}
})
});
启动服务查询结果
TIP:如果在查询作者的时候,不指定查询作者的书的信息,那么定义在AuthorType里查询作者书本信息的逻辑就不会走,省服务器资源,好评
文原接链: https://tomoya92.github.io/2019/05/31/nodejs-express-graphql-tutorial/
连接数据库
安装mongoose
yarn add mongoose
修改 server.js
const express = require("express");
const graphqlHTTP = require("express-graphql");
const schema = require("./schema/schema");
const mongoose = require("mongoose");
const app = express();
// 连接数据库
mongoose.connect("mongodb://127.0.0.1/graphql-js-demo", {
useNewUrlParser: true
});
mongoose.connection.once("open", function() {
console.log("connected to database!");
});
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
graphiql: true
})
);
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
创建models
定义mongoose模型,创建 models 文件夹
book.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const bookSchema = new Schema({
name: String,
authorId: String
});
module.exports = mongoose.model("Book", bookSchema);
author.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const authorSchema = new Schema({
name: String,
age: String
});
module.exports = mongoose.model("Author", authorSchema);
修改 schema/schema.js
添加两个添加数据的方法
const Book = require("../models/book");
const Author = require("../models/author");
// other code...
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt }
},
resolve(parent, args) {
let author = new Author({
name: args.name,
age: args.age
});
return author.save();
}
},
addBook: {
type: AuthorType,
args: {
name: { type: GraphQLString },
authorId: { type: GraphQLString }
},
resolve(parent, args) {
let book = new Book({
name: args.name,
authorId: args.authorId
});
return book.save();
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
启动服务调用 addAuthor addBook 两个方法保存数据
修改其它查询的实现,之前是从静态数据里筛选的,现在改成从 mongodb 里查,修改完后完整代码如下
schema/schema.js
const graphql = require("graphql");
const _ = require("lodash");
const Book = require("../models/book");
const Author = require("../models/author");
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLInt,
GraphQLID,
GraphQLList
} = graphql;
const BookType = new GraphQLObjectType({
name: "Book",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args) {
return Author.findById(parent.authorId);
}
}
})
});
const AuthorType = new GraphQLObjectType({
name: "Author",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({ authorId: parent.id });
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Book.findById(args.id);
}
},
author: {
type: AuthorType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Author.findById(args.id);
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({});
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args) {
return Author.find({});
}
}
}
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt }
},
resolve(parent, args) {
let author = new Author({
name: args.name,
age: args.age
});
return author.save();
}
},
addBook: {
type: AuthorType,
args: {
name: { type: GraphQLString },
authorId: { type: GraphQLString }
},
resolve(parent, args) {
let book = new Book({
name: args.name,
authorId: args.authorId
});
return book.save();
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
参考
原文链接:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Spring Boot 集成 Swagger 构建接口文档
- Spring Boot 2.x(十):构建优雅的RESTful接口
- 微服务实战(二):落地微服务架构到直销系统(构建消息总线框架接口)
- 用Java构建一个简单的WebSocket聊天项目之新增HTTP接口调度
- 使用Django 2.0构建Python Restful服务:四)创建Web服务api接口
- 使用Django 2.0构建Python Restful服务:四)创建Web服务api接口
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
互联网运营实战手册
李春雷 / 人民邮电出版社 / 2017-4 / 49.80元
为什么网络推广做不起来?微信文章也是套路?标题党的背后是什么?把服务器搞瘫痪的活动是怎么玩出来的?社群究竟要如何运营?数据又该如何运营?你会任务分解吗? 《互联网运营实战手册》详细剖析了网站(产品)的运营技巧与实战,涵盖实用的互联网运营方法,是作者从多年的实战中提炼出的运营心得和精华,涉及运营技巧、运营工具和运营思维方法。详细讲解了用户运营、内容运营、新媒体运营、社群运营、活动运营和数据运营......一起来看看 《互联网运营实战手册》 这本书的介绍吧!