GraphQL ロゴGraphQL

引数の渡し方

REST APIと同様に、GraphQL APIでもエンドポイントに引数を渡すことが一般的です。スキーマ言語で引数を定義することで、型チェックが自動的に行われます。各引数には名前と型を指定する必要があります。例えば、基本的な型に関するドキュメントでは、rollThreeDiceというエンドポイントがありました。

type Query {
rollThreeDice: [Int]
}

「three」をハードコーディングする代わりに、numDice個のサイコロを、それぞれnumSides面で振る、より一般的な関数を作成したい場合があります。GraphQL スキーマ言語に引数を追加するには、次のようにします。

type Query {
rollDice(numDice: Int!, numSides: Int): [Int]
}

Int!の感嘆符は、numDiceがnullでないことを示しています。つまり、サーバーコードを簡素化するために、検証ロジックの一部を省略できます。numSidesをnullにすることができ、デフォルトではサイコロは6面であると仮定します。

これまでのところ、リゾルバー関数は引数を受け取っていませんでした。リゾルバーが引数を受け取る場合、それらは1つの「args」オブジェクトとして、関数の最初の引数として渡されます。そのため、rollDiceは次のように実装できます。

var root = {
rollDice: args => {
var output = []
for (var i = 0; i < args.numDice; i++) {
output.push(1 + Math.floor(Math.random() * (args.numSides || 6)))
}
return output
},
}

ES6のデストラクチャリング代入を使用すると、これらのパラメーターのフォーマットがわかっているので便利です。そのため、rollDiceは次のように記述することもできます。

var root = {
rollDice: ({ numDice, numSides }) => {
var output = []
for (var i = 0; i < numDice; i++) {
output.push(1 + Math.floor(Math.random() * (numSides || 6)))
}
return output
},
}

デストラクチャリングに慣れているなら、これは少し見やすいでしょう。なぜなら、rollDiceが定義されているコード行で、引数が何かがわかるからです。

このrollDice APIをホストするサーバーの全コードは次のとおりです。

var express = require("express")
var { createHandler } = require("graphql-http/lib/use/express")
var { buildSchema } = require("graphql")
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
rollDice(numDice: Int!, numSides: Int): [Int]
}
`)
// The root provides a resolver function for each API endpoint
var root = {
rollDice: ({ numDice, numSides }) => {
var output = []
for (var i = 0; i < numDice; i++) {
output.push(1 + Math.floor(Math.random() * (numSides || 6)))
}
return output
},
}
var app = express()
app.all(
"/graphql",
createHandler({
schema: schema,
rootValue: root,
})
)
app.listen(4000)
console.log("Running a GraphQL API server at localhost:4000/graphql")

このAPIを呼び出す際には、各引数を名前で渡す必要があります。上記のサーバーの場合、6面サイコロを3個振るには、次のGraphQLクエリを実行できます。

{
rollDice(numDice: 3, numSides: 6)
}

node server.jsでこのコードを実行し、http://localhost:4000/graphqlにアクセスすると、このAPIを試すことができます。

コードで引数を渡す場合、クエリ文字列全体を自分で構築するのを避ける方が一般的です。代わりに、$構文を使用してクエリで変数を定義し、変数を別々のマップとして渡すことができます。

例えば、上記のサーバーを呼び出すJavaScriptコードの一部は次のとおりです。

var dice = 3
var sides = 6
var query = `query RollDice($dice: Int!, $sides: Int) {
rollDice(numDice: $dice, numSides: $sides)
}`
fetch("/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
query,
variables: { dice, sides },
}),
})
.then(r => r.json())
.then(data => console.log("data returned:", data))

GraphQLで$dice$sidesを変数として使用することで、クライアント側でのエスケープ処理について心配する必要がなくなります。

基本的な型と引数の渡し方を使用すれば、REST APIで実装できるものは何でも実装できます。しかし、GraphQLはさらに強力なクエリをサポートしています。独自のオブジェクト型を定義する方法を学習すれば、複数のAPI呼び出しを1つのAPI呼び出しに置き換えることができます。

読み続ける →オブジェクト型