首頁 >web前端 >js教程 >使用node.js和mongodb創建GraphQl Server

使用node.js和mongodb創建GraphQl Server

Christopher Nolan
Christopher Nolan原創
2025-02-18 10:37:13972瀏覽

使用node.js和mongodb創建GraphQl Server

鑰匙要點

  • >使用node.js並Express來建立服務器並將MongoDB與Mongoose集成以進行數據管理,從而增強了服務器有效地處理查詢和突變的能力。
  • >
  • >使用Express-GraphQL中間件在服務器上實現GraphQl,該中間件簡化了HTTP請求的處理和JSON響應的輸出,重點是創建用戶友好的JSON格式。
  • 定義一個由類型,查詢和突變組成的GraphQL模式,以精確管理數據交互,以確保數據結構與MongoDB模型一致性和安全性一致。
  • >>>>>
  • >通過利用GraphQl查詢來在單個HTTP請求中獲取特定數據字段來優化數據檢索,從而大大降低了傳輸的數據量並改善了性能,尤其是在具有較慢的網絡連接的移動設備上。
  • >使用Postman之類的工具來測試GraphQL端點,以驗證查詢和突變的設置和功能,以確保服務器對各種數據請求正確響應。
  • >
  • 本文是由Ryan Chenkie審查的。感謝SitePoint所有的同行評審員製作SitePoint內容的最佳狀態!
>從客戶端請求服務器的數據不是一個新概念。它允許應用程序加載數據而無需刷新頁面。這是單頁應用程序中最常使用的,該應用程序不是從服務器中獲取渲染頁面,而僅請求將其渲染在客戶端端所需的數據。

> 在過去幾年中,整個網絡上最常見的方法是其餘的建築風格。但是,這種方法給高數據需求應用帶來了一些局限性。在一個恢復的系統中,我們需要提出多個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架構

對於GraphQl,要了解我們需要定義架構的請求。 GraphQL模式不過是一組查詢和突變。您可以將查詢視為從數據庫中檢索和突變的資源,作為對數據庫的任何更新。我們將創建一個示例博客文章和評論貓鼬模型,然後我們將為其創建一些查詢和突變。

>

> mongoose模型

>讓我們從創建貓鼬模型開始。在這裡不會詳細介紹,因為貓鼬不是本文的重點。您可以在型號/blog-post.js和Models/comment.js。

中找到兩個模型

GraphQl types

喜歡貓鼬,在GraphQl中,我們需要定義數據結構。不同之處在於,我們為每個查詢定義和突變,可以輸入哪種類型的數據以及響應中發送的內容。如果這些類型不匹配,則會出現錯誤。儘管它看起來似乎是多餘的,但由於我們已經定義了貓鼬的模式模型,但它具有很大的優勢,例如:

>

您控制允許的內容,可以改善您的系統安全
  • >您控制允許的內容。這意味著您可以定義特定字段以永遠不會被檢索。例如:密碼或其他敏感數據
  • >它過濾了無效的請求,因此不採取進一步的處理,可以改善服務器的性能
  • >您可以在GraphQl/types/中找到GraphQl類型的源代碼。這是一個示例:
>

>在這裡,我們正在定義博客輸出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架構創建

>使用Mongoose模型和創建的GraphQL類型,我們現在可以創建我們的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

從查詢開始,讓我們從迄今為止創建的模型從一個示例中獲取。一個很好的例子是獲取博客文章及其所有評論。

> 在REST解決方案中,您必須為此提出兩個HTTP請求。一個可以獲取博客文章,另一個要獲得評論,這看起來像這樣:

在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/*的其他查詢。我們不會經歷每個示例,因為它們都與上面的示例相似。

>

突變

突變是可以在數據庫中進行某種更改的操作。像查詢一樣,我們可以在單個HTTP請求中分組不同的突變。通常是孤立的,例如“添加評論”或“創建博客文章”。儘管隨著應用程序和數據收集的複雜性不斷增長,用於分析,用戶體驗測試或複雜操作,網站或應用程序上的用戶操作可以觸發大量突變,從而向數據庫的不同資源觸發。按照我們的示例,對我們的博客文章的新評論可能意味著新的評論,並對博客文章評論的更新進行了更新。在休息解決方案中,您將擁有類似以下內容:

<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端點

>現在我們已經使用GraphQL路由創建了Express Server,並進行了一些查詢和突變,讓我們通過向其發送一些請求來對其進行測試。

有很多方法可以將獲取請求發送或將請求發佈到一個位置,例如:>
  • 瀏覽器 - 通過在瀏覽器中鍵入一個URL,您會發送get請求。這有無法發送發布請求
  • 的限制
  • curl - 用於命令行風扇。它可以將任何類型的請求發送到服務器。雖然,這不是最好的界面,但您無法保存請求,並且需要在命令行中寫所有內容,從我的角度來看,這不是理想的
  • GraphiQl - GraphQl的絕佳解決方案。這是一個瀏覽器IDE,您可以使用它來為服務器創建查詢。它具有一些很棒的功能,例如:語法突出顯示和鍵入
  • >
的解決方案比上述的解決方案更多。前兩個是最著名和最使用的。 GraphIQL是GraphQL團隊使用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>

使用node.js和mongodb創建GraphQl Server我們現在可以創建將具有JSON格式所需的GraphQl查詢和變量的主體:

>

>假設您已經導入了我提供的集合,則應該已經有一些可以測試的查詢和突變請求。由於我使用了硬編碼的Mongo ID,因此按順序運行請求,它們都應該成功。分析我在每個人的身體中放置的東西,您會發現這只是本文討論的內容的應用。另外,如果您不止一次運行第一個請求,因為它將是重複的ID,您可以看到如何返回錯誤:

使用node.js和mongodb創建GraphQl Server

結論

在本文中,我們介紹了GraphQL的潛力以及它與REST體系結構樣式的不同。這種新的查詢語言將對網絡產生重大影響。特別是對於更複雜的數據應用程序,現在可以準確地描述他們想要的數據,並使用單個HTTP請求請求。

我很想听聽您的來信:您如何看待GraphQl,您對此的經歷是什麼?

使用node.js和mongodb

創建GraphQl Server的常見問題

>如何為我的GraphQl Server設置MongoDB數據庫?

>為您的GraphQl Server設置MongoDB數據庫涉及多個步驟。首先,您需要在本地計算機上安裝MongoDB,或使用MongoDB Atlas等基於雲的MongoDB服務。安裝後,您可以創建一個新的數據庫和集合。然後,您可以使用MongoDB client從node.js應用程序連接到此數據庫。 Mongoose允許您為您的集合定義模式,並提供查詢和操縱數據的方法。

>

>如何為我的mongoDB數據定義GraphQl架構?您的數據和可以對其執行的操作。在node.js應用程序中,您可以使用GraphQl庫定義GraphQl架構。這涉及為您的數據,每種類型的字段定義類型以及可以在這些類型上執行的查詢和突變。這些類型應匹配MongoDB集合中的文檔的結構。

>

>如何處理GraphQl Server中的錯誤?

>

> >可以使用提供的formaterRor函數在GraphQl Server中完成錯誤處理。由阿波羅服務器。每當將錯誤丟棄在解析器中時,此功能就會稱為。它接收錯誤作為參數,應返回錯誤對象。該對象可以包括一條消息,狀態代碼和任何其他相關信息。您也可以在解析器中使用試用器/捕獲塊來捕獲和處理錯誤。

>

>如何優化我的GraphQl Server以進行性能? >有幾種方法可以優化GraphQl Server進行性能。一種方法是將批處理和緩存與諸如DataLoader之類的庫中。這可以減少對MongoDB數據庫的請求數量並改善響應時間。另一種方法是使用持久的查詢,該查詢可以減少發送到服務器的請求的大小。您還可以使用監視工具(例如Apollo Studio)來識別和修復性能瓶頸。

>如何保護我的GraphQl Server?

確保GraphQl Server涉及多個步驟。首先,您應該使用HTTP來加密客戶端和服務器之間的通信。您也可以使用頭盔之類的庫將安全標頭添加到HTTP響應中。對於身份驗證,您可以使用JSON Web令牌(JWT)並進行授權,可以使用GraphQl-Shield之類的庫。您還應該驗證和消毒用戶輸入以防止注射攻擊。

如何測試我的GraphQl Server?

可以使用單元測試,集成測試,集成測試,測試GraphQl Server進行測試graphQl Server和端到端測試。您可以使用Jest之類的庫來編寫測試和Supertest之類的庫來向您的服務器提出HTTP請求。您應該測試您的解析器,模式和mongoDB查詢和突變。

>如何使用像Heroku這樣的雲服務來完成我的GraphQl Server?

​​

AWS或Google Cloud。您還應該設置連續集成和連續部署(CI/CD)管道以自動化部署過程。這可以使用諸如github操作或jenkins之類的服務來完成。

如何監視我的graphql server?

>監視GraphQl Server可以使用Apollo Studio或New Relic等服務來完成。這些服務提供了有關服務器性能的見解,包括響應時間,錯誤率和使用統計信息。當您的服務器存在問題時,它們還可以提醒您。

>如何使用GraphQl-upload(例如GraphQl-upload)來完成使用GraphQl?

​​

處理文件上傳的文件上傳。該庫提供了一個可以在模式中使用的graphQlupload標量,並且可以在中間件中使用該庫來處理上傳的文件。 >

以上是使用node.js和mongodb創建GraphQl Server的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn