如何使用GraphQL,Koa和MongoDB設(shè)置功能強(qiáng)大的API(一)

15573815320235.jpg

構(gòu)建API非常有趣!特別是當(dāng)您可以利用Koa,GraphQL和MongoDB等現(xiàn)代技術(shù)時(shí)。

Koa是一個(gè)Node框架,就像Express是一個(gè)Node框架一樣。我們將用Koa替換Express,因?yàn)镵oa在回調(diào)時(shí)使用async / await語法。

入門

構(gòu)建API的先決條件如下:

  • 節(jié)點(diǎn)安裝
  • 文本編輯器; 我選擇Visual Studio Code
  • 終奌站
  • 瀏覽器

如果您擁有所需的一切,請繼續(xù) - 如果沒有,請安裝它們。

打開終端并創(chuàng)建一個(gè)節(jié)點(diǎn)項(xiàng)目,如下所示:
15573815950021.jpg

到目前為止,我們創(chuàng)建了項(xiàng)目文件夾,并初始化了一個(gè)新的Node項(xiàng)目。現(xiàn)在我們有了可用的NPM軟件包,可用于安裝Koa,Mongo和GraphQL。

讓我們安裝koaNPM。

npm i koa

啟動(dòng)一個(gè)新的Koa服務(wù)器非常簡單。我們需要的只是一個(gè)server.js文件,其內(nèi)容如下:

const Koa = require('koa');

const app = new Koa();

app.listen(9000);

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

使用Node啟動(dòng)項(xiàng)目:


15573816496082.jpg

安裝GraphQL

我們需要兩個(gè)軟件包來使用Koa設(shè)置GraphQL:koa-mount和koa-graphql

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

GraphQL要求我們將初始模式傳遞給GraphQL服務(wù)器。讓我們創(chuàng)建一個(gè)。

我們將把graphQL架構(gòu)放在 graphql/schema.js

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

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

module.exports = schema;

我們將我們的初始函數(shù)傳遞QuerybuildSchema函數(shù)

注意:請注意該參數(shù)的參數(shù)buildSchema是模板文字。如果不熟悉,我建議你看一下這篇文章。

現(xiàn)在我們可以將初始模式傳遞給GraphQL服務(wù)器。

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

別忘了導(dǎo)入koa-mount,koa-graphql最后是schema.js。

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

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

15573818065573.jpg

初始設(shè)置完成。它還不是很有用。理想情況下,我們想查詢GraphQL以將數(shù)據(jù)保存到我們的mongodb并從那里讀取。

設(shè)置MongoDB

為了使用GraphQL進(jìn)行讀寫,我們需要一個(gè)可以讀取的地方。這就是Mongo派上用場的地方。我們將從那里保存并讀取我們的數(shù)據(jù)。

為了簡單起見,我們將為Mongo使用云實(shí)例。前往mlab.com并創(chuàng)建用戶和mongo數(shù)據(jù)庫。

創(chuàng)建mongoDB數(shù)據(jù)庫
創(chuàng)建數(shù)據(jù)庫后,您將需要數(shù)據(jù)庫的用戶。

創(chuàng)建MongoDB用戶

現(xiàn)在您可以使用與Mongoose配對的mongoDB。您的數(shù)據(jù)庫的遠(yuǎn)程URL將是這樣的:

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

安裝mongoose

npm i mongoose

創(chuàng)建database.js文件

我們?yōu)閿?shù)據(jù)庫連接創(chuàng)建一個(gè)專用文件。

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;

注意:確保使用數(shù)據(jù)庫的用戶名和憑據(jù)。

這段代碼將嘗試連接到遠(yuǎn)程mongodb。我們現(xiàn)在需要在某處調(diào)用它。

打開server.jsrequire調(diào)用initDB方法。

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

initDB();

如果我們正確地完成了所有工作,我們的控制臺應(yīng)該告訴我們我


15573821320252.jpg

請注意不斷刷新服務(wù)器有多煩人?讓我們用一個(gè)名為的包來解決這個(gè)問題pm2。

PM2是具有內(nèi)置負(fù)載均衡器的Node.js應(yīng)用程序的生產(chǎn)過程管理器。它允許您永久保持應(yīng)用程序活動(dòng),在不停機(jī)的情況下重新加載應(yīng)用程序,并促進(jìn)常見的系統(tǒng)管理任務(wù)。

添加一個(gè)調(diào)用start我們的腳本package.json:

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

Pm2在后臺運(yùn)行,這釋放了我們的終端。如果您想要停止該過程,請運(yùn)行pm2 kill?,F(xiàn)在我們不必一直重啟服務(wù)器,pm2自動(dòng)完成。

注意:pm2 logs將控制臺日志語句返回給終端。

MongoDB模型

如果你曾經(jīng)使用過Mongo,你就知道m(xù)ongoDB可以讓我們?yōu)槲覀兊臄?shù)據(jù)創(chuàng)建模型。這是我們構(gòu)建數(shù)據(jù)外觀的簡潔方法。

創(chuàng)建文件夾模型并在文件內(nèi)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);

注意:我們的架構(gòu)中沒有ID字段。那是因?yàn)镸ongoose
默認(rèn)會為所有模式分配一個(gè)ID。

大。我們還添加一個(gè)集合和一些虛擬數(shù)據(jù)。gadgets在這種情況下,集合名稱必須將我們的args名稱映射為復(fù)數(shù)形式。

15573822600003.jpg

創(chuàng)建集合后,以JSON格式插入文檔,如下所示:


15573822695160.jpg

這就是Mongo的全部。讓我們用GraphQL獲取數(shù)據(jù)。

GraphQL查詢

GraphQL也要求我們創(chuàng)建類型。把它想象成計(jì)算機(jī)的指令。

graphql/gadgetType.js

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLString } = graphql;

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

  })
});

module.exports = GadgetType;

注意我們創(chuàng)建了一個(gè)graphql類型。在字段內(nèi),我們可以指定給定類型的屬性。

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中解構(gòu)的GraphQLObjectTypeGraphQLObjectType類型。這些是graphQL的原始類型。

創(chuàng)建graphQL類型也會授予我們在創(chuàng)建查詢時(shí)使用的類型提示。

我們需要做的最后一件事是重構(gòu)我們的schema.js。我們想通過查詢argsid。

導(dǎo)入Gadget模型,gadgetGraphQLTypegraphql類型和GraphQLSchema,GraphQLObjectTypeGraphQLStringgraphQLschema.js。

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

接下來我們需要一個(gè)根查詢。每個(gè)GraphQL查詢都以大括號開頭{}:

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

  }
})

瞧!在字段內(nèi),我們可以指定gadget查詢。

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

請注意args查詢中的三個(gè)屬性:

  • type - gadgetGraphQLType在這種情況下,這是查詢的類型。
  • args - 我們可以為graphql查詢提供參數(shù),例如: gadgets(id: "1")
  • 解決 - 我們?nèi)绾谓鉀Q查詢?一旦進(jìn)行查詢,應(yīng)該怎么辦?這里我們按id 返回Gadget 模型。

最后導(dǎo)出它。

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

文件schema.js文件應(yīng)如下所示:

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
});

現(xiàn)在轉(zhuǎn)到http:// localhost:9000 / graphql并進(jìn)行查詢。

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

這就是我們應(yīng)該最終得到的!

15573824944085.jpg

到目前為止,我們可以讀取我們的數(shù)據(jù),但我們很有可能需要編輯我們的數(shù)據(jù)記錄/文檔。任何完整的數(shù)據(jù)平臺都需要一種修改服務(wù)器端數(shù)據(jù)的方法。

其他章節(jié)

如何使用GraphQL,Koa和MongoDB設(shè)置功能強(qiáng)大的API(一)
如何使用GraphQL,Koa和MongoDB設(shè)置功能強(qiáng)大的API(二)
如何使用GraphQL,Koa和MongoDB設(shè)置功能強(qiáng)大的API(三)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容