Graphql的使用
Graphql是一种查询语言,用于API的设计和查询。它的主要特点是提供了一种灵活、高效、类型安全的数据查询方式,可以减少API的请求次数,提高数据传输的效率。
它与Restful API对比
- 数据获取
RESTful API是面向资源的,每个资源都有一个独立的URL,通过HTTP方法(GET、POST、PUT、DELETE等)对资源进行操作。GraphQL是面向数据的,使用查询语言来描述需要获取的数据结构。
- 数据结构
RESTful API返回的数据结构是固定的,通常是JSON或XML格式。GraphQL允许客户端精确地指定需要返回的数据结构,避免了不必要的数据传输。
- 性能
RESTful API的性能通常受到请求和响应的大小和数量的限制。GraphQL通过在单个请求中获取多个数据点来提高性能,从而减少了请求次数和响应大小。
- 缓存
RESTful API使用HTTP缓存来提高性能,因为每个资源都有一个独立的URL。GraphQL可以使用相同的查询来获取不同的数据,这意味着客户端可以缓存查询并重复使用它们。
- 安全性
RESTful API使用HTTP方法来操作资源,因此需要对每个方法进行身份验证和授权。GraphQL使用单个HTTP方法(POST)来处理所有请求,因此需要在查询语言中定义安全性。
js搭建一个Graphql服务
import Koa from 'koa';
import mount from 'koa-mount';
import { createHandler } from 'graphql-http/lib/use/koa';
import { user_schema } from './lib/user_schema';
const app = new Koa();
// 定义数据源
const users = [
{ id: '1', name: 'Alice', age: 25, email: 'alice@example.com', posts: [{ id: '1', title: 'First Post', content: 'Hello world!' }] },
{ id: '2', name: 'Bob', age: 30, email: 'bob@example.com', posts: [{ id: '2', title: 'Second Post', content: 'What a wonderful day!' }] },
];
// 定义resolvers
const root = {
hello: () => 'Hello, world!',
user: ({ id }) => users.find(user => user.id === id),
};
// 将GraphQL服务挂载到'/graphql'路径下
app.use(mount('/graphql', createHandler({
schema: user_schema,
rootValue: root,
graphiql: true // 开启GraphQL的可视化界面
})));
// 启动服务器
app.listen(3000, () => {
console.log('Server started on http://localhost:3000');
});
user_schemal.js
import { buildSchema } from 'graphql';
const user_schema = buildSchema(`
type Query {
hello: String
user(id: ID!): User
}
type User {
id: ID
name: String
age: Int
email: String
posts: [Post]
}
type Post {
id: ID
title: String
content: String
}
`);
export default {user_schema}
通过GraphQL查询,这个需要支持GraphQL的客户端,发送查询语句
{
hello,
user(id:1){
id,
name,
age,
posts{
id,
title,
content
}
}
}
返回的数据
{
"data": {
"hello": "Hello, world!",
"user": {
"id": "1",
"name": "Alice",
"age": 25,
"posts": [
{
"id": "1",
"title": "First Post",
"content": "Hello world!"
}
]
}
}
}
创建schema
schema文件定义了需要的数据结构,graphQL有自己的类型系统
graphql.cn/learn/schema/#type-syst...
定义resolvers
对每个查询字段,需要生成对应的函数
本作品采用《CC 协议》,转载必须注明作者和本文链接
我也有在用
我已经把这个东西已经全部删除了,就在今天. 看起来很好用,实际逻辑稀碎
graphql 已经不算新技术了,但这么长时间里,应用始终还是占少数,是有其原因的。
我提几点使用过程中的问题,看看大家有没有较好的解决方案:
1.查询复杂度如何控制?
graphql 的查询复杂度是一个很大的问题,如果没有控制,很容易就会出现恶意查询,导致服务器崩溃。
举一个例子:
这样的查询,会导致服务器查询 1000 * 1000 = 1000000 条数据,这是不可接受的。
2.查询缓冲如何实现?
graphql 的查询是非常灵活的,如果没有缓冲,每次查询都会导致数据库查询,这是不可接受的。
举一个例子:
以上查询中当前用户和所加入的团队所有者中都有相同的用户ID,如果没有缓冲,将导致多次查询。
更不用说我在使用中采用一些服务端指令,类似 @can 这类会在执行中进行数据库查询,而其中的结果难以在上下文中使用。
这种灵活的结构同时也让关系型数据库的 SQL 的组装变得非常困难,很难做到按需组装查询。
这么看,所有看起来是优势的特性都是有代价的。这让我想起我最近在使用 lighthouse 在介绍资源处置风险时提到的那句蜘蛛侠的台词“With great power there must also come great responsibility”
这就变得矛盾,从服务端看:越是灵活的 API 维护成本就变的越高,我们越需要限制它的作用,直到达到某个平衡状态。
要说起我认为 graphql 真正的价值其实还是在沟通方面,无论前端还是后端工程师都基于其 schema 暴露出数据的结构来构建程序。 schema 即充当了程序沟通的标准,也成为了前后端工程师(只不过我同时为两者,比较精分)沟通的桥梁。
上面这帖子有部分是使用 github copilot 插件在 markdown 文档中写的,大家能看出来是哪部分吗?