尝试使用GraphQL
中国人积极尝试使用GraphQL进行实验。
自从第一次了解到GraphQL已经过去了大约一年,最近在一个活动中听到了它,因此决定试试看。这篇文章就是对此的总结。
REST和GraphQL
REST是一种思维方式,而GraphQL则是一种查询语言,虽然进行比较有些奇怪,但从我接触的印象来看,如下所述。
-
- RESTの場合、複雑なクエリを扱う場合に複数回のデータアクセスが必要になるが、1度のアクセスで取得できる (最初はこれぐらいしかメリットを感じてなかった)。
-
- RESTよりもIF設計の自由度は低いが、データモデルだけを気にすればよいため、設計の手間が少ない。
-
- RESTよりもドキュメントやスタブを作る手間が低い (Swagger要らず)。
- GraphQLの場合、スキーマの定義で必須項目や型を定義できる( https://graphql.org/learn/schema/ )。
示例
我实际编写了一个基于Node.js的示例,如下所示。
基本上,只需以下页面上的信息就足以完成实现。
服务器端
在中国大陆,可以使用npm来安装所需的库和框架。
使用npm安装express、express-graphql和graphql模块。
let express=require('express')
let express_graphql = require('express-graphql');
let { buildSchema } = require('graphql');
let app = express();
app.use('/graphql', express_graphql({
// スキーマの定義
schema: buildSchema(`
type Query {
id: String
}
`),
// サーバ側の値
rootValue: {
id: "hoge"
}
}));
app.listen(3000, ()=> console.log('Listening on http://localhost:3000/graphql'));
客户端
客户端主要使用curl进行了测试。
有以下两种访问方法(可能是由库提供的)。
客户端主要使用curl进行了尝试。
访问方法有以下两种(可能是通过库提供的)。
客户端主要使用curl进行了测试。
访问方法有以下两种模式(也许是依赖于库)。
$ curl -H "Content-Type:application/graphql" -X POST http://localhost:3000/graphql -d 'query { id }'
{"data":{"id":"hoge"}}
在JSON格式的情况下,可以通过以下形式进行数据访问:「{ “query” : “XXXXX”}」。
$ curl -H "Content-Type:application/json" -X POST http://localhost:3000/graphql -d '{ "query" : "query { id }" }'
{"data":{"id":"hoge"}}
如果返回除了固定值以外的情况
服务器端
如果返回了除固定值以外的结果,需要像以下这样记录模式和处理。
let express=require('express')
let express_graphql = require('express-graphql');
let { buildSchema } = require('graphql');
let app = express();
app.use('/graphql', express_graphql({
schema: buildSchema(`
type Query {
getUser(id:Int) : String
}
`),
rootValue: {
getUser:function(args){
console.log(args);
return "uid:" + args.id;
}
}
}));
app.listen(3000, ()=> console.log('Listening on http://localhost:3000/graphql'));
客户端。
同样是固定值,我们展示两种情况的例子。
$ curl -H "Content-Type:application/graphql" -X POST http://localhost:3000/graphql -d '{ query : getUser(id:1234) }'
{"data":{"getUser":"uid:12345"}}
$ curl -H "Content-Type:application/json" -X POST http://localhost:3000/graphql -d '{ "query" : "query { getUser(id:12345) }" }'
{"data":{"getUser":"uid:12345"}}
此外,GraphQL 的一项优点是可以同时执行多个查询,写法如下:
$ curl -H "Content-Type:application/json" -X POST http://localhost:3000/graphql -d '{ "query" : "query { a:getUser(id:1234) b:getUser(id:2234) }" }'
{"data":{"a":"uid:1234","b":"uid:2234"}}
如果要执行多个相同的查询,请使用别名功能。
可以通过在“别名:查询”中进行编写,来将不同参数的相同查询进行组合处理。
类型定义
如果要定义自己的类型,描述如下。
服务器端 (Sā fú
let express=require('express')
let express_graphql = require('express-graphql');
let { buildSchema } = require('graphql');
let app = express();
app.use('/graphql', express_graphql({
schema: buildSchema(`
type User {
id:Int
name:String
}
type Query {
getUser(id:Int) : User
}
`),
rootValue: {
getUser:function(args){
console.log(args);
let user = {
id: args.id,
name: "Mike"
};
return user;
}
}
}));
app.listen(3000, ()=> console.log('Listening on http://localhost:3000/graphql'));
客户端方
Note: This translation may vary depending on the context.
$ curl -H "Content-Type:application/graphql" -X POST http://localhost:3000/graphql -d 'query { getUser(id:1234){name} }'
{"data":{"getUser":{"name":"Mike"}}}
$ curl -H "Content-Type:application/json" -X POST http://localhost:3000/graphql -d '{ "query" : "query { getUser(id:1234){ id, name }}" }'
{"data":{"getUser":{"id":1234,"name":"Mike"}}}
如果仅需获取名称,请使用以下选项。
$ curl -H "Content-Type:application/json" -X POST http://localhost:3000/graphql -d '{ "query" : "query { getUser(id:1234){ name }}" }'
{"data":{"getUser":{"name":"Mike"}}}
赠品
绘制图表
在使用GraphQL时,可以使用graphqlviz轻松创建图表。(还有其他可供选择吗?)
可以使用npm进行安装。
$ npm install -g graphqlviz
$ graphqlviz -v http://localhost:3000/graphql | dot -Tpng -o graph.png
另外,通过将模式定义放在另一个文件中,也可以通过以下方式实现。
$ graphqlviz -g test.gql | dot -Tpng -o graph.png
type User {
id:Int
name:String
}
type Query {
getUser(id:Int) : User
}
在尚未找到在Node.js中使用外部文件进行模式定义的方法… (虽然已确认可以使用以下方法执行)
buildSchema(fs.readFileSync('./test.gql', 'utf8'))
添加注释和描述
在GraphQL的模式定义中,可以通过在前面加上“#”符号来进行注释。
type User {
# User ID
id:Int
name:String
}
type Query {
getUser(id:Int) : User
}
而且,通过以下方式说不定可以写下文档字符(类似于Java的javadoc)。
"""
ユーザ情報
"""
type User {
"ユーザID"
id: Int
" 名前"
name: String
}
type Query {
getUser(id:Int) : User
}