GraphQL を理解する: GraphQL の概要

王林
リリース: 2023-08-28 22:05:12
オリジナル
1428 人が閲覧しました

###############概要###

GraphQL は、アドホック クエリと操作のためのエキサイティングな新しい API です。非常に柔軟性があり、多くの利点があります。これは、グラフやツリー形式で整理されたデータを公開するのに特に適しています。 Facebook は GraphQL を 2012 年に開発し、2015 年にオープンソース化しました。 理解 GraphQL:GraphQL 简介

これは急速に成長し、最も注目されているテクノロジーの 1 つになりました。多くの革新的な企業が本番環境で GraphQL を採用し、使用しています。このチュートリアルでは次のことを学びます:

GraphQLの原理

RESTとの比較

アーキテクチャを設計する方法
  • GraphQLサーバーのセットアップ方法
  • クエリの実装方法と変更方法
  • その他の高度なテーマ
  • GraphQL のハイライトは何ですか?
  • GraphQL が最大限に発揮されるのは、データが階層またはグラフに編成されており、フロントエンドがその階層またはグラフのさまざまなサブセットにアクセスしたい場合です。 NBA を公開するアプリケーションを考えてみましょう。チーム、選手、コーチ、チャンピオンシップ、そしてそれぞれに関する大量の情報があります。以下にいくつかのサンプルクエリを示します:
現在ゴールデンステート ウォリアーズの名簿に載っている選手の名前は何ですか?

ワシントン・ウィザーズのスターティングプレイヤーの名前、身長、年齢は何ですか?

現役で最も多くのチャンピオンシップを獲得したコーチは誰ですか?
  • コーチは何年にどのチームで優勝しましたか?
  • 最も多くの MVP 賞を受賞した選手は誰ですか?
  • このような質問は何百件もできるでしょう。これらすべてのクエリをフロントエンドに公開し、ユーザーや製品マネージャーが新しいエキサイティングなクエリ コンテンツを思いついたときに、新しいクエリ タイプで API を簡単に拡張できる API を設計する必要があることを想像してみてください。
  • これは些細な問題ではありません。 GraphQL はまさにこの問題を解決するために設計されており、すぐにわかるように、単一の API エンドポイントで膨大な機能を提供します。
  • GraphQL と REST

GraphQL の詳細に入る前に、現在最も人気のあるタイプの Web API である REST と比較してみましょう。

REST はリソース指向モデルに従います。リソースが選手、コーチ、チームである場合、次のようなエンドポイントがある可能性があります:

###/プレーヤー###

/プレイヤー/

###/コーチ###

/コーチ/

    ###/チーム### ###/チーム/######
  • 通常、ID のないエンドポイントは ID のリストのみを返しますが、ID を持つエンドポイントはリソースに関する完全な情報を返します。もちろん、他の方法で API を設計することもできます (たとえば、/players エンドポイントは各プレーヤーの名前または各プレーヤーに関するすべての情報を返すこともできます)。
  • 動的環境では、このアプローチの問題は、アンダーフェッチ (例: ID のみを取得し、さらに情報が必要な場合) またはオーバーフェッチ (例: 名前のみが必要な場合) のいずれかになることです。
  • これらは難しい質問です。十分な ID が取得できない場合、100 個の ID を取得した場合、各プレーヤーの情報を取得するために 100 回の個別の API 呼び出しを行う必要があります。オーバーフェッチすると、必要のない大量のデータの準備と送信に多くのバックエンド時間とネットワーク帯域幅が浪費されます。
  • REST を介してこの問題を解決するには、複数の方法があります。多くのカスタム エンドポイントを設計して、それぞれが必要なデータを正確に返すことができます。このソリューションはスケーラブルではありません。 API の一貫性を保つのは困難です。それを進化させるのは難しいです。文書化して使用するのは難しいです。これらのカスタム エンドポイント間に多くの重複がある場合、それを維持するのは困難です。
  • 次の追加のエンドポイントを検討してください:
  • ###/プレーヤの名前###
  • /players/names_and_championships
  • /チーム/スタート

別のアプローチは、少数の共通エンドポイントを保持し、多数のクエリ パラメーターを提供することです。このソリューションは複数のエンドポイントの問題を回避しますが、REST モデルの原則に違反するため、一貫して開発および保守することが困難です。

GraphQL はこのアプローチを限界まで行っていると言えるでしょう。明示的に定義されたリソースは考慮されず、ドメイン全体のサブグラフが考慮されます。

GraphQL型システム

GraphQL は、型とプロパティで構成される型システムを使用してドメインをモデル化します。すべてのプロパティにはタイプがあります。プロパティの型は、ID、String、Boolean など、GraphQL によって提供される基本型の 1 つであることも、ユーザー定義の型であることもできます。グラフのノードはユーザー定義タイプであり、エッジはユーザー定義タイプの属性です。

例えば、「プレイヤー」タイプに「チーム」タイプの「チーム」属性がある場合、各プレイヤーノードからチームノードへのエッジがあることを意味します。すべての型は、GraphQL ドメイン オブジェクト モデルを記述するスキーマで定義されます。
  • これは、NBA ドメインの非常に簡素化されたアーキテクチャです。プレーヤーには名前、最も関係のあるチーム (はい、プレーヤーがあるチームから別のチームに移ることがあるのは知っています)、およびプレーヤーが獲得したチャンピオンシップの数があります。
  • チームには名前、名簿、およびチームが獲得したチャンピオンシップの数があります。
  • リーリー
  • 事前定義されたエントリ ポイントもあります。それらはクエリ、変更、サブスクライブです。フロントエンドはエントリ ポイントを通じてバックエンドと通信し、必要に応じてカスタマイズできます。
これは、すべてのプレーヤーを返す単純なクエリです:

type Query {
    allPlayers: [Player!]!
}
ログイン後にコピー

感叹号表示该值不能为空。对于 allPlayers 查询,它可以返回空列表,但不能返回 null。另外,这意味着列表中不能有空玩家(因为它包含 Player!)。

设置 GraphQL 服务器

这是一个基于 Node-Express 的成熟 GraphQL 服务器。它有一个内存中的硬编码数据存储。通常,数据将位于数据库中或从其他服务获取。数据定义如下(如果您最喜欢的球队或球员未能入选,请提前致歉):

let data = {
  "allPlayers": {
    "1": {
      "id": "1",
      "name": "Stephen Curry",
      "championshipCount": 2,
      "teamId": "3"
    },
    "2": {
      "id": "2",
      "name": "Michael Jordan",
      "championshipCount": 6,
      "teamId": "1"
    },
    "3": {
      "id": "3",
      "name": "Scottie Pippen",
      "championshipCount": 6,
      "teamId": "1"
    },
    "4": {
      "id": "4",
      "name": "Magic Johnson",
      "championshipCount": 5,
      "teamId": "2"
    },
    "5": {
      "id": "5",
      "name": "Kobe Bryant",
      "championshipCount": 5,
      "teamId": "2"
    },
    "6": {
      "id": "6",
      "name": "Kevin Durant",
      "championshipCount": 1,
      "teamId": "3"
    }
  },

  "allTeams": {
    "1": {
      "id": "1",
      "name": "Chicago Bulls",
      "championshipCount": 6,
      "players": []
    },
    "2": {
      "id": "2",
      "name": "Los Angeles Lakers",
      "championshipCount": 16,
      "players": []
    },
    "3": {
      "id": "3",
      "name": "Golden State Warriors",
      "championshipCount": 5,
      "players": []
    }
  }
}
ログイン後にコピー

我使用的库是:

const express = require('express');
const graphqlHTTP = require('express-graphql');
const app = express();
const { buildSchema } = require('graphql');
const _ = require('lodash/core');
ログイン後にコピー

这是构建架构的代码。请注意,我向 allPlayers 根查询添加了几个变量。

schema = buildSchema(`
  type Player {
    id: ID
    name: String!
    championshipCount: Int!
    team: Team!
  }
  
  type Team {
    id: ID
    name: String!
    championshipCount: Int!
    players: [Player!]!
  }
  
  type Query {
    allPlayers(offset: Int = 0, limit: Int = -1): [Player!]!
  }`
ログイン後にコピー

关键部分来了:连接查询并实际提供数据。 rootValue 对象可能包含多个根。

这里,只有 allPlayers。它从参数中提取偏移量和限制,对所有玩家数据进行切片,然后根据团队 ID 设置每个玩家的团队。这使得每个玩家都是一个嵌套对象。

rootValue = {
  allPlayers: (args) => {
    offset = args['offset']
    limit = args['limit']
    r = _.values(data["allPlayers"]).slice(offset)
    if (limit > -1) {
      r = r.slice(0, Math.min(limit, r.length))
    }
    _.forEach(r, (x) => {
      data.allPlayers[x.id].team   = data.allTeams[x.teamId]
    })
    return r
  },
}
ログイン後にコピー

最后,这是 graphql 端点,传递架构和根值对象:

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

app.listen(3000);

module.exports = app;
ログイン後にコピー

graphiql 设置为 true 使我们能够使用出色的浏览器内 GraphQL IDE 来测试服务器。我强烈推荐它来尝试不同的查询。

使用 GraphQL 进行临时查询

万事俱备。让我们导航到 http://localhost:3000/graphql 并享受一些乐趣。

我们可以从简单的开始,只包含玩家姓名列表:

query justNames {
    allPlayers {
    name
  }
}

Output:

{
  "data": {
    "allPlayers": [
      {
        "name": "Stephen Curry"
      },
      {
        "name": "Michael Jordan"
      },
      {
        "name": "Scottie Pippen"
      },
      {
        "name": "Magic Johnson"
      },
      {
        "name": "Kobe Bryant"
      },
      {
        "name": "Kevin Durant"
      }
    ]
  }
}
ログイン後にコピー

好吧。我们这里有一些超级巨星。毫无疑问。让我们尝试一些更奇特的东西:从偏移量 4 开始,有 2 名玩家。对于每个球员,返回他们的名字和他们赢得的冠军数量以及他们的球队名称和球队赢得的冠军数量。

query twoPlayers {
    allPlayers(offset: 4, limit: 2) {
    name
    championshipCount
    team {
      name
      championshipCount
    }
  }
}

Output:

{
  "data": {
    "allPlayers": [
      {
        "name": "Kobe Bryant",
        "championshipCount": 5,
        "team": {
          "name": "Los Angeles Lakers",
          "championshipCount": 16
        }
      },
      {
        "name": "Kevin Durant",
        "championshipCount": 1,
        "team": {
          "name": "Golden State Warriors",
          "championshipCount": 5
        }
      }
    ]
  }
}
ログイン後にコピー

所以科比·布莱恩特随湖人队赢得了 5 个总冠军,湖人队总共获得了 16 个总冠军。凯文·杜兰特在勇士队只赢得了一次总冠军,而勇士队总共赢得了五次总冠军。

GraphQL 突变

魔术师约翰逊无疑是场上的魔术师。但如果没有他的朋友卡里姆·阿卜杜勒·贾巴尔,他不可能做到这一点。让我们将 Kareem 添加到我们的数据库中。我们可以定义 GraphQL 突变来执行从图表中添加、更新和删除数据等操作。

首先,让我们向架构添加突变类型。它看起来有点像函数签名:

type Mutation {
    createPlayer(name: String, 
                 championshipCount: Int, 
                 teamId: String): Player
}
ログイン後にコピー

然后,我们需要实现它并将其添加到根值中。该实现只是获取查询提供的参数并将一个新对象添加到 data['allPlayers']。它还确保正确设置团队。最后,它返回新的玩家。

  createPlayer: (args) => {
    id = (_.values(data['allPlayers']).length + 1).toString()
    args['id'] = id
    args['team'] = data['allTeams'][args['teamId']]
    data['allPlayers'][id] = args
    return data['allPlayers'][id]
  },
ログイン後にコピー

要实际添加 Kareem,我们可以调用突变并查询返回的玩家:

mutation addKareem {
  createPlayer(name: "Kareem Abdul-Jabbar", 
               championshipCount: 6, 
               teamId: "2") {
    name
    championshipCount
    team {
      name
    }
  }
}

Output:

{
  "data": {
    "createPlayer": {
      "name": "Kareem Abdul-Jabbar",
      "championshipCount": 6,
      "team": {
        "name": "Los Angeles Lakers"
      }
    }
  }
}
ログイン後にコピー

这是一个关于突变的黑暗小秘密......它们实际上与查询完全相同。您可以在查询中修改数据,并且可能只从突变中返回数据。 GraphQL 不会查看您的代码。查询和突变都可以接受参数并返回数据。它更像是语法糖,可以使您的架构更具人类可读性。

高级主题

订阅

订阅是 GraphQL 的另一个杀手级功能。通过订阅,客户端可以订阅每当服务器状态发生变化时就会触发的事件。订阅是后来引入的,不同的框架以不同的方式实现。

验证

GraphQL 将验证针对架构的每个查询或突变。当输入数据具有复杂形状时,这是一个巨大的胜利。您不必编写烦人且脆弱的验证代码。 GraphQL 将为您处理好它。

架构自省

您可以检查和查询当前架构本身。这为您提供了动态发现架构的元能力。下面是一个返回所有类型名称及其描述的查询:

query q {
  __schema {
    types {
      name
      description            
    }
  }
ログイン後にコピー

结论

GraphQL 是一项令人兴奋的新 API 技术,与 REST API 相比,它具有许多优势。它背后有一个充满活力的社区,更不用说Facebook了。我预测它将很快成为前端的主要内容。试一试。你会喜欢的。

以上がGraphQL を理解する: GraphQL の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート