如何使用GraphQL,Koa和MongoDB设置功能强大的API(一)

15573815320235.jpg

构建API非常有趣!特别是当您可以利用Koa,GraphQL和MongoDB等现代技术时。

Koa是一个Node框架,就像Express是一个Node框架一样。我们将用Koa替换Express,因为Koa在回调时使用async / await语法。

入门

构建API的先决条件如下:

  • 节点安装
  • 文本编辑器; 我选择Visual Studio Code
  • 终奌站
  • 浏览器

如果您拥有所需的一切,请继续 - 如果没有,请安装它们。

打开终端并创建一个节点项目,如下所示:
15573815950021.jpg

到目前为止,我们创建了项目文件夹,并初始化了一个新的Node项目。现在我们有了可用的NPM软件包,可用于安装Koa,Mongo和GraphQL。

让我们安装koaNPM。

npm i koa

启动一个新的Koa服务器非常简单。我们需要的只是一个server.js文件,其内容如下:

const Koa = require('koa');

const app = new Koa();

app.listen(9000);

app.on('error', err => {
  log.error('server error', err)
});

使用Node启动项目:


15573816496082.jpg

安装GraphQL

我们需要两个软件包来使用Koa设置GraphQL:koa-mount和koa-graphql

npm i koa-mount koa-graphql
15573816781488.jpg
15573816850846.jpg

GraphQL要求我们将初始模式传递给GraphQL服务器。让我们创建一个。

我们将把graphQL架构放在 graphql/schema.js

const { buildSchema } = require('graphql');

const schema = buildSchema(`
 type Query {
   hello: String
 }
`);

module.exports = schema;

我们将我们的初始函数传递QuerybuildSchema函数

注意:请注意该参数的参数buildSchema是模板文字。如果不熟悉,我建议你看一下这篇文章。

现在我们可以将初始模式传递给GraphQL服务器。

app.use(mount('/graphql', graphqlHTTP({
 schema: schema,
 graphiql: true
})))

别忘了导入koa-mountkoa-graphql最后是schema.js

const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('./graphql/schema');

然后,如果我们前往localhost:9000/graphql

15573818065573.jpg

初始设置完成。它还不是很有用。理想情况下,我们想查询GraphQL以将数据保存到我们的mongodb并从那里读取。

设置MongoDB

为了使用GraphQL进行读写,我们需要一个可以读取的地方。这就是Mongo派上用场的地方。我们将从那里保存并读取我们的数据。

为了简单起见,我们将为Mongo使用云实例。前往mlab.com并创建用户和mongo数据库。

创建mongoDB数据库
创建数据库后,您将需要数据库的用户。

创建MongoDB用户

现在您可以使用与Mongoose配对的mongoDB。您的数据库的远程URL将是这样的:

mongodb://:@ds213615.mlab.com:13615/koa-graphql

安装mongoose

npm i mongoose

创建database.js文件

我们为数据库连接创建一个专用文件。

const mongoose = require('mongoose');

const initDB = () => {

  mongoose.connect(
    'mongodb://indrek:graphql1@ds213615.mlab.com:13615/koa-graphql',
    { useNewUrlParser: true }
  );

  mongoose.connection.once('open', () => {
    console.log('connected to database');
  });

}

module.exports = initDB;

注意:确保使用数据库的用户名和凭据。

这段代码将尝试连接到远程mongodb。我们现在需要在某处调用它。

打开server.jsrequire调用initDB方法。

const  initDB  =  require(' ./database ');

initDB();

如果我们正确地完成了所有工作,我们的控制台应该告诉我们我


15573821320252.jpg

请注意不断刷新服务器有多烦人?让我们用一个名为的包来解决这个问题pm2

PM2是具有内置负载均衡器的Node.js应用程序的生产过程管理器。它允许您永久保持应用程序活动,在不停机的情况下重新加载应用程序,并促进常见的系统管理任务。

添加一个调用start我们的脚本package.json:

"scripts": {
  "start": "pm2 start server.js"
},
15573821891475.jpg

Pm2在后台运行,这释放了我们的终端。如果您想要停止该过程,请运行pm2 kill。现在我们不必一直重启服务器,pm2自动完成。

注意:pm2 logs将控制台日志语句返回给终端。

MongoDB模型

如果你曾经使用过Mongo,你就知道mongoDB可以让我们为我们的数据创建模型。这是我们构建数据外观的简洁方法。

创建文件夹模型并在文件内gadgets.js输入:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

/*
  notice there is no ID. That's because Mongoose will assign
  an ID by default to all schemas
*/

const GadgetSchema = new Schema({
  name: String,
  release_date: Date,
  by_company: String,
  price: Number,
});

module.exports = mongoose.model('Gadget', GadgetSchema);

注意:我们的架构中没有ID字段。那是因为Mongoose
默认会为所有模式分配一个ID。

大。我们还添加一个集合和一些虚拟数据。gadgets在这种情况下,集合名称必须将我们的args名称映射为复数形式。

15573822600003.jpg

创建集合后,以JSON格式插入文档,如下所示:


15573822695160.jpg

这就是Mongo的全部。让我们用GraphQL获取数据。

GraphQL查询

GraphQL也要求我们创建类型。把它想象成计算机的指令。

graphql/gadgetType.js

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLString } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({

  })
});

module.exports = GadgetType;

注意我们创建了一个graphql类型。在字段内,我们可以指定给定类型的属性。

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLObjectType } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    release_date: { type: GraphQLString },
    by_company: { type: GraphQLString },
    price: { type: GraphQLString }
  })
});

module.exports = GadgetType;

注意我们从graphQL中解构的GraphQLObjectTypeGraphQLObjectType类型。这些是graphQL的原始类型。

创建graphQL类型也会授予我们在创建查询时使用的类型提示。

我们需要做的最后一件事是重构我们的schema.js。我们想通过查询argsid。

导入Gadget模型,gadgetGraphQLTypegraphql类型和GraphQLSchemaGraphQLObjectTypeGraphQLStringgraphQLschema.js

onst { GraphQLSchema,GraphQLObjectType,GraphQLString } =  require(' graphql ');
const  gadgetGraphQLType  =   require(' ./gadgetType ');
const  Gadget  =  require(' ../models/gadget ');

接下来我们需要一个根查询。每个GraphQL查询都以大括号开头{}:

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {

  }
})

瞧!在字段内,我们可以指定gadget查询。

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(args.id)
      }
    }
  }
})

请注意args查询中的三个属性:

  • type - gadgetGraphQLType在这种情况下,这是查询的类型。
  • args - 我们可以为graphql查询提供参数,例如: gadgets(id: "1")
  • 解决 - 我们如何解决查询?一旦进行查询,应该怎么办?这里我们按id 返回Gadget 模型。

最后导出它。

module.exports = new GraphQLSchema({
  query: RootQuery
});

文件schema.js文件应如下所示:

const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require('graphql');
const gadgetGraphQLType =  require('./gadgetType');
const Gadget = require('../models/gadget');

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(args.id)
      }
    }
  }
})

module.exports = new GraphQLSchema({
  query: RootQuery
});

现在转到http:// localhost:9000 / graphql并进行查询。

{
    gadget(id: "5c4e188efb6fc05326ad9264") {
        name
    price
    by_company
    release_date
    id
  }
}

这就是我们应该最终得到的!

15573824944085.jpg

到目前为止,我们可以读取我们的数据,但我们很有可能需要编辑我们的数据记录/文档。任何完整的数据平台都需要一种修改服务器端数据的方法。

其他章节

如何使用GraphQL,Koa和MongoDB设置功能强大的API(一)
如何使用GraphQL,Koa和MongoDB设置功能强大的API(二)
如何使用GraphQL,Koa和MongoDB设置功能强大的API(三)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355