
構(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)目,如下所示:
到目前為止,我們創(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)目:

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


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ù)傳遞Query給buildSchema函數(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:

初始設(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.js并require調(diào)用initDB方法。
const initDB = require(' ./database ');
initDB();
如果我們正確地完成了所有工作,我們的控制臺應(yīng)該告訴我們我

請注意不斷刷新服務(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"
},

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ù)形式。

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

這就是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)的GraphQLObjectType和GraphQLObjectType類型。這些是graphQL的原始類型。
創(chuàng)建graphQL類型也會授予我們在創(chuàng)建查詢時(shí)使用的類型提示。
我們需要做的最后一件事是重構(gòu)我們的schema.js。我們想通過查詢argsid。
導(dǎo)入Gadget模型,gadgetGraphQLTypegraphql類型和GraphQLSchema,GraphQLObjectType,GraphQLString從graphQL到schema.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)該最終得到的!

到目前為止,我們可以讀取我們的數(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(三)