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

欢迎来到我们的第三部分系列,我们在其中设置了一个强大的API 到目前为止,我们已经实现了基本的CRUD功能。

随着我们的应用程序的增长,我们的Mutation数也在增 为了拥有尽可能干净的代码库,我们应该将mutations提取到专用文件中。这样我们就可以确保我们的代码是模块化的,并分成可维护的块。

让我们创建一个文件夹graphql/mutations和文件夹中创建addGadget.js,updateGadget和removeGadget文件..

我们只是将Mutation对象放入文件并导出它们。

将addGadgetMutation移动到单独的文件
graphql/mutations/addGadget.js

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

module.exports = {
  type: gadgetGraphQLType,
  args: {
    name: { type: GraphQLString },
    release_date: { type: GraphQLString },
    by_company: { type: GraphQLString },
    price: { type: GraphQLString }
  },
  resolve(parent, args) {
    const newGadget = new Gadget({
      name: args.name,
      release_date: args.release_date,
      by_company: args.by_company,
      price: args.price,
    })

    return newGadget.save();
  }
};

更新mutations;
graphql/mutations/updateGadget.js

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

module.exports = {
  type: gadgetGraphQLType,
  args: {
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    release_date: { type: GraphQLString },
    by_company: { type: GraphQLString },
    price: { type: GraphQLString }
  },
  resolve(parent, args) {
    return Gadget.findById(args.id)
      .then(gadget => {
        gadget.name = args.name,
        gadget.release_date = args.release_date,
        gadget.by_company = args.by_company,
        gadget.price = args.price

        return gadget.save()

      })
      .then(updatedGadget => updatedGadget)
      .catch(err => console.log(err))
  }
};

最后是删除mutations。
graphql/mutations/removeGadget.js

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

module.exports = {
  type: gadgetGraphQLType,
  args: {
    id: { type: GraphQLString }
  },
  resolve(parent, args) {
    return Gadget.findOneAndDelete(args.id).exec()
      .then(gadget => gadget.remove())
      .then(deletedGadget => deletedGadget)
      .catch(err => console.log(err))
  }
};

我们将它们放在单独的文件中后,我们就可以更改graphql/mutations.js文件了。

const { GraphQLObjectType, GraphQLString } = require('graphql');

const addGadget = require('./mutations/addGadget');
const updateGadget = require('./mutations/updateGadget');
const removeGadget = require('./mutations/removeGadget');

const Mutation = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    addGadget,
    updateGadget,
    removeGadget,
  }
})

module.exports = Mutation;

非常简洁

这就是我们的项目现在的样子;

15573832643778.jpg

我们的GraphQL API正在形成良好的状态。到目前为止,我们有一个专门的mutations文件夹。让我们对查询做同样的事情。

为查询创建一个文件夹 - graphql/queries并将rootQuery.js文件放在那里。

在rootQuery.js文件内部,我们放置了只获取数据的所有查询。这样我们就有了用于查询和mutations的单独文件夹。查询和mutations之间的区别很简单 - 查询只是从数据库中读取数据,mutations会改变我们数据库的状态。

graphql/queries/rootQuery.js

const { GraphQLObjectType, GraphQLString, GraphQLList } =  require('graphql');

const gadgetGraphQLType =  require('./../gadgetType');
const Gadget = require('../../models/gadget');
const queryAllGadgets = require('./queryAllGadgets')

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

  }
})

module.exports = RootQuery;

将rootQuery导入到我们的 schema.js

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

const RootQuery = require('./queries/rootQuery');
const Mutations = require('./mutations');


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

现在在rootQuery中我们指定所有查询。创建一个文件,用于获取所有数据并按ID获取数据。

  • graphql/queries/queryAllGadgets.js
  • graphql/queries/queryGadgetById.js
    将以下逻辑放在里面 graphql/queries/queryGadgetById.js
const { GraphQLString } =  require('graphql');
const gadgetGraphQLType = require('./../gadgetType');
const Gadget = require('../../models/gadget');

module.exports = {
  type: gadgetGraphQLType,
  args: { id: { type: GraphQLString }},
  resolve(parent, args) {
    return Gadget.findById(args.id)
  }
},

并获取所有数据 - graphql/queries/queryAllGadgets.js

const { GraphQLList } =  require('graphql');
const gadgetGraphQLType = require('./../gadgetType');
const Gadget = require('../../models/gadget');

module.exports = {
  type: new GraphQLList(gadgetGraphQLType),
  args: {},
  resolve() {
    return Gadget.find({})
  }
}

请注意新类型GraphQLList- 如果我们想要返回对象列表(在这种情况下为所有数据),则使用此类型。

现在我们必须将查询导入到我们的 rootQuery

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

const Gadget = require('../../models/gadget');
const queryAllGadgets = require('./queryAllGadgets')
const queryGadgetById = require('./queryGadgetById');

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    queryGadgetById,
    queryAllGadgets,
  }
})

module.exports = RootQuery;

瞧!现在,让我们从数据库中查询所有数据。

15573833506873.jpg

这是GraphQL查询;

{
  queryAllGadgets {
    name,
    id,
    price,
    release_date,
    by_company
  }
}

我们的项目结构应如下所示;

15573833657744.jpg

不要忘记更新我们使用的路径gadgetType(mutations和查询)

const gadgetGraphQLType = require('./../types/gadgetType');

测试我们的查询

在转向更高级的概念之前,我想向您展示一个工具,让我们可以查询graphql查询,如果您曾经使用过postman或Insomnia,您会感到宾至如归。

我使用Insomnia,因为它是免费的,具有开箱即用的强大功能,并且是开源的。

免责声明:我与Insomnia无关 - 我只是喜欢这个工具。

15573834500207.jpg

打开该工具,创建一个名为的新请求queryAllGadgets。在顶部我们的localhost地址(http:// localhost:9000 / graphql)并指定正文是graphQL。


15573835071141.jpg

最后,将graphQL查询放在body请求中。

15573835129605.jpg

我们现在可以随意地查询graphQL,就像我们使用REST一样。如果REST可以做到这一点,GraphQL也可以。

其他章节

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

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