> 在過去幾年中,整個網絡上最常見的方法是其餘的建築風格。但是,這種方法給高數據需求應用帶來了一些局限性。在一個恢復的系統中,我們需要提出多個HTTP請求,以獲取我們想要的所有數據,這具有重大的性能影響。如果有一種方法在單個HTTP請求中請求多個資源怎麼辦? > 介紹GraphQl,一種查詢語言,可以統一客戶端和服務器端之間的通信。它允許客戶端在單個請求中準確地描述所需的數據。
> 在本文中,我們將使用GraphQl路由創建一個Node.js/Express Server,該路由將處理我們所有的查詢和突變。然後,我們將通過發送一些帖子請求並使用Postman分析結果來測試此路線。>您可以在此處找到此應用程序的完整源代碼。我還製作了一個郵遞員,您可以在此處下載。
>>在Express Server上設置GraphQl端點
第一件事是使用Express Framework創建我們的Node.js服務器。我們還將將MongoDB與Mongoose一起用於數據持久性,而Babel使用ES6。由於該代碼在運行時被轉移到ES5,因此無需構建過程。這是在index.js中完成的:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
>在app.js中,我們將啟動服務器,使用mongo數據庫連接並創建GraphQl路由。
在本文上下文中,上面代碼中最相對的部分是我們定義GraphQl路由的位置。我們使用Facebook GraphQL團隊開發的Express中間件Express-GraphQL。這將通過GraphQL處理HTTP請求並返回JSON響應。為此,我們需要在下一節中討論的GraphQL模式的選項中通過。我們還將選項設置為真實。這使JSON的響應非常印刷,使其更易於閱讀。<span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>>
graphQl架構
> mongoose模型
GraphQl types
您控制允許的內容,可以改善您的系統安全
>在這裡,我們正在定義博客輸出graphql類型,在創建查詢和突變時,我們將進一步使用。請注意,結構與貓鼬模型Blogpost有多相似。這似乎可以重複工作,但這些是分開的關注點。 Mongoose模型定義了數據庫的數據結構,GraphQL類型定義了服務器的查詢或突變中所接受的規則。
<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>
graphQl架構創建
在這裡,我們導出一個graphqlschema,在其中定義了兩個屬性:查詢和突變。 GraphQlobjectType是眾多GraphQL類型之一。特別是,您可以指定:
>我們傳遞到字段的查詢和突變變量是普通的JavaScript對象。鍵是突變或查詢名稱。這些值是帶有配置的普通JavaScript對象,該對象告訴GraphQl如何處理它們。讓我們以以下GraphQl查詢為例:
>>要使GrahPQL了解該查詢的方法,我們需要定義Blogposts和評論查詢。因此,我們的查詢變量將是這樣的:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>>
突變也是如此。這是為了解釋我們在查詢或突變中所擁有的鍵與我們在查詢中的名稱之間存在直接關係。現在讓我們看看這些查詢和突變中的每一個。
><span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>QUERIES
從查詢開始,讓我們從迄今為止創建的模型從一個示例中獲取。一個很好的例子是獲取博客文章及其所有評論。
在GraphQl中,我們只能在一個http請求中進行以下查詢:
>我們可以在一個請求中獲取我們想要的所有數據,這單獨提高了性能。我們還可以要求我們要使用的確切屬性。在上面的示例中,響應只會帶來博客文章的標題和描述,評論只會帶來文字。
。<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>僅從每個資源中檢索所需的字段,可以對網頁或應用程序的加載時間產生巨大影響。讓我們看一下評論,這些評論也具有_id和postid屬性。這些中的每一個都是小的,每個都確切的12個字節(不使用對象鍵計數)。當它是單個或幾個評論時,這幾乎沒有影響。當我們談論的是200條評論時,我們甚至都不會使用的4800個字節。這可以對應用程序加載時間產生重大影響。這對於資源有限的設備(例如移動設備)通常具有較慢的網絡連接。
為此,我們需要告訴GraphQl如何為每個特定查詢獲取數據。讓我們看看查詢定義的示例:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
>在這裡,我們正在創建一個根據ID參數檢索單個博客文章的查詢。請注意,我們正在指定以前創建的類型,該類型驗證了查詢的輸出。我們還設置了一個ARGS對象,並具有此查詢所需的參數。最後,我們查詢數據庫並返回數據的解決方案函數。
> 為了進一步優化獲取數據的過程並利用了MongoDB上的投影功能,我們正在處理GraphQL為我們提供與Mongoose兼容的投影的AST。因此,如果我們進行以下查詢:
<span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>>由於我們只需要從數據庫中獲取標題和描述,因此getProcotion函數將生成一個有效的投影:
<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>您可以在源代碼中查看graphql/queries/*的其他查詢。我們不會經歷每個示例,因為它們都與上面的示例相似。
>
突變
<span>// graphql/index.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLSchema </span></span><span><span>}</span> from 'graphql'; </span> <span>import mutations from './mutations'; </span><span>import queries from './queries'; </span> <span>export default new GraphQLSchema({ </span> <span>query: new GraphQLObjectType({ </span> <span>name: 'Query', </span> <span>fields: queries </span> <span>}), </span> <span>mutation: new GraphQLObjectType({ </span> <span>name: 'Mutation', </span> <span>fields: mutations </span> <span>}) </span><span>}); </span>>使用GraphQl,您只能在一個http請求中使用以下內容進行操作:
>
query <span>{ </span> blogPosts <span>{ </span> _id<span>, </span> title <span>} </span> comments <span>{ </span> text <span>} </span><span>} </span>請注意,查詢和突變的語法完全相同,只是將查詢更改為突變。 我們可以從突變中詢問數據,就像我們從查詢中相同的方式。通過不指定片段,就像我們在上面的BlogPostCommentin中的查詢中一樣,我們只是在問一個真或錯誤的返回值,這通常足以確認操作。或者我們可以要求提供一些數據,例如對附加組件突變,這對於僅檢索服務器上生成的數據很有用。
> 然後,讓我們在服務器中定義我們的突變。突變是完全作為查詢創建的:
這個突變將添加新的博客文章,並在成功(如果成功)返回true。請注意,在類型中,我們指定將要返回的內容。在Args中,從突變中收到的論點。 and lesolve()函數與查詢定義完全一樣。
<span>{ </span> <span>blogPosts: {...}, </span> <span>comments: {...} </span><span>} </span>>
測試GraphQl端點
在這三個中,我建議GraphiQl,儘管我更喜歡並最重要的是郵遞員。該工具絕對是API測試的預付款。它提供了一個直觀的接口,您可以在其中創建並保存任何類型的請求的集合。您甚至可以為您的API創建測試,並單擊按鈕。它還具有協作功能,並使其能夠共享請求的集合。因此,我創建了一個可以在此處下載的,然後您可以將其導入到Postman。如果您沒有安裝郵遞員,我絕對建議您這樣做。
>>讓我們從運行服務器開始。您應該安裝4個或更高的節點;如果您還沒有,我建議使用NVM安裝它。然後,我們可以在命令行中運行以下內容:
>服務器現在可以接收請求,因此讓我們在Postman上創建一些。我們的GraphQL路由設置為/GraphQl,因此首先要做的就是將位置設置為我們要指導我們的請求的位置,即http:// localhost:8080/graphql。然後,我們需要指定它是GET還是郵政請求。儘管您可以使用其中的任何一個,但我更喜歡發布,因為它不會影響URL,從而使其更清潔。我們還需要配置隨請求隨附的標頭,在我們的情況下,我們只需要添加與應用程序/JSON等於的內容類型。這是Postman中的所有外觀:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
我們現在可以創建將具有JSON格式所需的GraphQl查詢和變量的主體:
>假設您已經導入了我提供的集合,則應該已經有一些可以測試的查詢和突變請求。由於我使用了硬編碼的Mongo ID,因此按順序運行請求,它們都應該成功。分析我在每個人的身體中放置的東西,您會發現這只是本文討論的內容的應用。另外,如果您不止一次運行第一個請求,因為它將是重複的ID,您可以看到如何返回錯誤:
我很想听聽您的來信:您如何看待GraphQl,您對此的經歷是什麼?
使用node.js和mongodb
創建GraphQl Server的常見問題>如何為我的mongoDB數據定義GraphQl架構?您的數據和可以對其執行的操作。在node.js應用程序中,您可以使用GraphQl庫定義GraphQl架構。這涉及為您的數據,每種類型的字段定義類型以及可以在這些類型上執行的查詢和突變。這些類型應匹配MongoDB集合中的文檔的結構。
>> >可以使用提供的formaterRor函數在GraphQl Server中完成錯誤處理。由阿波羅服務器。每當將錯誤丟棄在解析器中時,此功能就會稱為。它接收錯誤作為參數,應返回錯誤對象。該對象可以包括一條消息,狀態代碼和任何其他相關信息。您也可以在解析器中使用試用器/捕獲塊來捕獲和處理錯誤。
>處理文件上傳的文件上傳。該庫提供了一個可以在模式中使用的graphQlupload標量,並且可以在中間件中使用該庫來處理上傳的文件。
以上是使用node.js和mongodb創建GraphQl Server的詳細內容。更多資訊請關注PHP中文網其他相關文章!