關(guān)于 GraphQL 快速入門

GraphQL是什么?
一種用于 API 的查詢語言,GraphQL 既是一種用于 API 的查詢語言也是一個(gè)滿足你數(shù)據(jù)查詢的運(yùn)行時(shí)。
GraphQL 對(duì)你的 API 中的數(shù)據(jù)提供了一套易于理解的完整描述,使得客戶端能夠準(zhǔn)確地獲得它需要的數(shù)據(jù),而且沒有任何冗余,也讓 API 更容易地隨著時(shí)間推移而演進(jìn),還能用于構(gòu)建強(qiáng)大的開發(fā)者工具。
GraphQL 是一個(gè)用于 API 的查詢語言,是一個(gè)使用基于類型系統(tǒng)來執(zhí)行查詢的服務(wù)端運(yùn)行時(shí)(類型系統(tǒng)由你的數(shù)據(jù)定義)。GraphQL 并沒有和任何特定數(shù)據(jù)庫或者存儲(chǔ)引擎綁定,而是依靠你現(xiàn)有的代碼和數(shù)據(jù)支撐。
關(guān)于SQL
SQL 指結(jié)構(gòu)化查詢語言,全稱是 Structured Query Language。
在您的網(wǎng)站中使用 SQL,比如要?jiǎng)?chuàng)建一個(gè)顯示數(shù)據(jù)庫中數(shù)據(jù)的網(wǎng)站,您需要:
1、RDBMS 數(shù)據(jù)庫程序(比如 MS Access、SQL Server、MySQL)?
2、使用服務(wù)器端腳本語言,(比如 PHP 、 ASP、Node)?
3、使用 SQL 來獲取您想要的數(shù)據(jù) 4、使用 HTML / CSS
如何使用
GraphQL 是一種描述客戶端如何向服務(wù)端請(qǐng)求數(shù)據(jù)的API語法,類似于 RESTful API 規(guī)范。
客戶端可以通過 HTTP GET 發(fā)送請(qǐng)求,請(qǐng)求的結(jié)構(gòu)如下所示:
http://myapi/graphql?query={me{name}}然后你的 GraphQL HTTP 服務(wù)器應(yīng)當(dāng)能夠處理 HTTP GET 方法。
// server.jsconst express = require('express')const { graphqlHTTP } = require('express-graphql')const schema = require('./schema')const cors = require('cors')const app = express()app.use(cors({origin: 'http://localhost:3000',methods: 'GET,POST,OPTIONS,DELETE,PUT'}))app.use('/graphql', graphqlHTTP({schema,graphiql: true}))app.listen(4000, () => {console.log('服務(wù)器啟動(dòng):http://localhost:4000')})
express-graphql 的 npm 包是用來創(chuàng)建一個(gè) GraphQL HTTP 服務(wù)。用它結(jié)合常規(guī) Express 來運(yùn)行 GraphQL,作用是處理請(qǐng)求然后返回?cái)?shù)據(jù)。
graphql 的 npm 包是 GraphQL 規(guī)范的語法實(shí)現(xiàn),用于在 Node.js 環(huán)境中運(yùn)行。GraphQL API 基于類型和字段的方式進(jìn)行組織。所以這個(gè)包的作用定義類型和字段提供 API 方法。
// schema.jsconst graphql = require('graphql')const { GraphQLObjectType, GraphQLString, GraphQLSchema, GraphQLList, GraphQLNonNull } = graphqlconst User = new GraphQLObjectType({name: 'User',fields: () => ({id: { type: GraphQLString },name: { type: GraphQLString }})})const UserInfo = { id: "1", name: "張三" }const RootQuery = new GraphQLObjectType({name: 'RootQuery',fields: {me: {type: User,args: {// 參數(shù)},resolve (parent, args) {return UserInfo}}}})module.exports = new GraphQLSchema({query: RootQuery})
然后啟動(dòng)服務(wù),當(dāng)我們?cè)L問 http://localhost:4000/graphql?query={me{name}} 頁面會(huì)查詢出下面結(jié)果:
{"data": {"me": {"name": "張三"}}}
GraphQL 主要是作用于數(shù)據(jù)接口,比如前端后端交互。客戶端自由篩選去獲取服務(wù)端事先定義好的數(shù)據(jù),提高了交互接口的靈活性。比如上述接口,只有 name 字段,現(xiàn)在我又想訪問 id 字段,只需要在接口請(qǐng)求的時(shí)候帶上你要獲取那些字段就可以。
http://localhost:4000/graphql?query={me{name,id}}向你的 API 發(fā)出一個(gè) GraphQL 請(qǐng)求就能準(zhǔn)確獲得你想要的數(shù)據(jù),不多不少。GraphQL 查詢總是返回可預(yù)測的結(jié)果。使用 GraphQL 的應(yīng)用可以工作得又快又穩(wěn),因?yàn)榭刂茢?shù)據(jù)的是我們的應(yīng)用,而不是服務(wù)器。
GraphQL 查詢不僅能夠獲得資源的屬性,還能沿著資源間引用進(jìn)一步查詢。典型的 REST API 請(qǐng)求多個(gè)資源時(shí)得載入多個(gè) URL,而 GraphQL 可以通過一次請(qǐng)求就獲取你應(yīng)用所需的所有數(shù)據(jù)。這樣一來,即使是比較慢的移動(dòng)網(wǎng)絡(luò)連接下,使用 GraphQL 的應(yīng)用也能表現(xiàn)得足夠迅速。
const graphql = require('graphql')const { GraphQLObjectType, GraphQLString, GraphQLSchema, GraphQLList, GraphQLNonNull } = graphqlconst categories = [{ id: '1', name: '圖書' },{ id: '2', name: '手機(jī)' },{ id: '3', name: '面包' },{ id: '4', name: '電腦' },]// products.category 對(duì)應(yīng)的是 categories.id 表示分類idconst products = [{ id: '1', name: '深入淺出nodeJS', category: '1' },{ id: '2', name: '高級(jí)程序設(shè)計(jì)', category: '1' },{ id: '3', name: '華為手機(jī)', category: '2' },{ id: '4', name: 'mac電腦', category: '4' },]const Category = new GraphQLObjectType({name: 'Category',fields: () => ({id: { type: GraphQLString },name: { type: GraphQLString },products: {type: new GraphQLList(Product),resolve (parent) {// parent是當(dāng)前分類,根據(jù)分類找到對(duì)應(yīng)的產(chǎn)品列表return products.filter(item => item.category === parent.id)}}})})const Product = new GraphQLObjectType({name: 'Product',fields: () => ({id: { type: GraphQLString },name: { type: GraphQLString },category: {type: Category,resolve (parent) {// category: '1' 根據(jù)分類的id找到分類對(duì)應(yīng)的對(duì)象return categories.find(item => item.id === parent.category)}}})})// 定義根類型const RootQuery = new GraphQLObjectType({name: 'RootQuery',fields: {// 根據(jù)ID查詢分類getCategory: {type: Category,args: {id: { type: GraphQLString },},resolve (parent, args) {return categories.find((item) => item.id === args.id)}},// 查詢所有分類getCategoryList: {type: new GraphQLList(Category),args: {},resolve (parent, args) {return categories}},// 根據(jù)ID查詢產(chǎn)品getProduct: {type: Product,args: {id: { type: GraphQLString },},resolve (parent, args) {return products.find((item) => item.id === args.id)}},// 查詢所有產(chǎn)品getProductList: {type: new GraphQLList(Product),args: {},resolve (parent, args) {return products}}}})module.exports = new GraphQLSchema({query: RootQuery})
一個(gè)分類下面是有多個(gè)產(chǎn)品,這種一對(duì)多的關(guān)系。當(dāng)我們查詢分類的時(shí)候,還能查出具體分類里面的產(chǎn)品列表,這種關(guān)聯(lián)關(guān)系就是沿著資源間引用進(jìn)一步查詢的特點(diǎn)。
