GraphQL是什么
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。
读完这句也没有获得很明确的信息,为便于理解,我们以Django为例,两张表的定义如下所示
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=100)
notes = models.TextField()
category = models.ForeignKey(
Category, related_name='ingredients', on_delete=models.CASCADE)
def __str__(self):
return self.name
如果我们按照传统RESTFul API的写法,大抵可以写成下面这样子
class IngredientSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Ingredient
fields = ['name', 'notes', 'category']
class IngredientViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = Ingredient.objects.all()
serializer_class = IngredientSerializer
不过在我有限的后端开发经历过程中,曾经遇到这种情况,跟手机端的同学对接接口,有的接口需要Ingredient
的全部字段,而有的接口又只需Ingredient
的notes
字段,这个带来的麻烦在于
- 一个接口,数据字段给多了,可以做到通用,但是难免浪费流量
- 接口分开,代码冗余,毕竟除了返回字段不一样,查询过程是一样的
姑且不看GraphQL是如何解决这个问题的,先来看一下结果
➜ ~ curl -iX POST http://raspberrypi.local:8000/graphql -H 'content-type: application/json' -d '{"query": "{allIngredients {id name category{name}}}"}'
HTTP/1.1 200 OK
Date: Tue, 03 Dec 2019 03:04:18 GMT
Server: WSGIServer/0.2 CPython/3.7.4
Content-Type: application/json
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Content-Length: 242
Set-Cookie: csrftoken=F0zhAsDXcAxO78m2VXL6Hj7d3wnsLG8xPPurzEVWQJk5JesB5pwij7mQrNnMslsk; expires=Tue, 01 Dec 2020 03:04:18 GMT; Max-Age=31449600; Path=/; SameSite=Lax
{"data":{"allIngredients":[{"id":"1","name":"Eggs","category":{"name":"Dairy"}},{"id":"2","name":"Milk","category":{"name":"Dairy"}},{"id":"3","name":"Beef","category":{"name":"Meat"}},{"id":"4","name":"Chicken","category":{"name":"Meat"}}]}}
若我只要notes
字段,又该如何?
curl -iX POST http://raspberrypi.local:8000/graphql -H 'content-type: application/json' -d '{"query": "{allIngredients {notes}}"}'
HTTP/1.1 200 OK
Date: Tue, 03 Dec 2019 03:06:09 GMT
Server: WSGIServer/0.2 CPython/3.7.4
Content-Type: application/json
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Content-Length: 181
Set-Cookie: csrftoken=YGb6Eyb31DjBs4YUFfcuz3bAOre9p1oyfKy0nwxmM4uHsOrECvV0aL9IG2tD6fog; expires=Tue, 01 Dec 2020 03:06:09 GMT; Max-Age=31449600; Path=/; SameSite=Lax
{"data":{"allIngredients":[{"notes":"Good old eggs"},{"notes":"Comes from a cow"},{"notes":"Much like milk, this comes from a cow"},{"notes":"Definitely doesn't come from a cow"}]}}
好像有一种魔力,我需要什么格式,接口就给我什么格式的数据,且看两次的查询参数
{"query": "{allIngredients {id name category{name}}}"}
和
{"query": "{allIngredients {notes}}"}
很明显,返回的数据结构跟查询数据结构颇为相似,而且是同一个接口,这是GraphQL的“魔法”,当然,数据库查询这一块无论用哪种方法都是一样的,在数据返回这块,GraphQL隐藏了复杂的后台处理过程,让数据获取方根据自己的需求,在GraphQL的规则之下,获取自己想要的数据,不多不少,刚刚好,这是初试GraphQL后我的实际使用观感
优/缺点
-
GraphQL
在接口数据的运用上洽到好处 - 后端的工作量初看是增加了,不过好在
GraphQL
与RESTFul
并非水火不融,二者可共存,可小范围试用 - 传统方法前端几乎可以无脑调用接口展示数据,使用
GraphQL
需要前端知悉后端逻辑,这很fullstack
-
GraphQL
工具链不算很完整,目前还在发展中,虽有不少大公司在尝鲜,但少有生产实践资料与经验,前景未明
数据库这一层所做之事均是一样的,数据查询这块做文章能带来多大的收益?不过前后端沟通成本也是一个问题,我能想到的是:若是全栈开发这么写倒是挺不错的
GraphQL
可持续关注,且听下回分解
参考
网友评论