原文地址
上一篇 Object Identification
Relay文档翻译目录
A faction has many ships in the Star Wars universe. Relay contains functionality
to make manipulating one-to-many relationships easy, using a standardized way
of expressing these one-to-many relationships. This standard connection
model offers ways of slicing and paginating through the connection.
在星球大战中一个faction有很多ships。Relay可以让处理一对多关系变得简单,用统一的方法来处理一对多关系。标准的connection模型提供了分片、分页的功能。
Let’s take the rebels, and ask for their first ship:
在rebels中查询第一个ship
query RebelsShipsQuery {
rebels {
name,
ships(first: 1) {
edges {
node {
name
}
}
}
}
}
yields
产出
{
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{
"node": {
"name": "X-Wing" }
}
]
}
}
}
That used the first
argument to ships
to slice the result set down to the
first one. But what if we wanted to paginate through it? On each edge, a cursor
will be exposed that we can use to paginate. Let’s ask for the first two this
time, and get the cursor as well:
这里在ships
上用了first
参数,从结果中截取了第一条记录。但是如果我们想分页呢?在每一个edge上,都会暴露出一个cursor,我们可以用它来分页。这次让我们获取前两条数据,并且同时返回cursor。
query MoreRebelShipsQuery {
rebels {
name,
ships(first: 2) {
edges {
cursor
node {
name
}
}
}
}
}
and we get back
我们得到:
{
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{
"cursor": "YXJyYXljb25uZWN0aW9uOjA=",
"node": {
"name": "X-Wing" }
},
{
"cursor": "YXJyYXljb25uZWN0aW9uOjE=",
"node": {
"name": "Y-Wing" }
}
]
}
}
}
Notice that the cursor is a base64 string. That’s the pattern from earlier
again, the server reminding us that this is an opaque string. We can pass this
string back to the server as the after
argument to the ships
field, which
will let us ask for the next three ships after the last one in the previous
result:
注意到cursor是base64字符串。这是我们之前见过的模式,再次提醒我们它对我们是不透明的。我们可以把它通过ship字段的after参数传回去,我们可以查询从最后一个返回的记录之后数,再3条记录。
query EndOfRebelShipsQuery {
rebels {
name,
ships(first: 3 after: "YXJyYXljb25uZWN0aW9uOjE=") {
edges {
cursor,
node {
name
}
}
}
}
}
gives us
{
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{
"cursor": "YXJyYXljb25uZWN0aW9uOjI=",
"node": {
"name": "A-Wing" }
},
{
"cursor": "YXJyYXljb25uZWN0aW9uOjM=",
"node": {
"name": "Millenium Falcon" }
},
{
"cursor": "YXJyYXljb25uZWN0aW9uOjQ=",
"node": {
"name": "Home One" }
}
]
}
}
}
Sweet! Let’s keep going and get the next four!
query RebelsQuery {
rebels {
name,
ships(first: 4 after: "YXJyYXljb25uZWN0aW9uOjQ=") {
edges {
cursor,
node {
name
}
}
}
}
}
yields
{
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": []
}
}
}
Hm. There were no more ships; guess there were only five in the system for
the rebels. It would have been nice to know that we’d reached the
end of the connection, without having to do another round trip in order
to verify that. The connection model exposes this capability with a type
called PageInfo
. So let’s issue the two queries that got us ships again,
but this time ask for hasNextPage
:
阿,没有更多的ship了,我们猜想这个rebel中只有5个ship。我们可以知道我们到了connection的尽头,我们并没有用其他技巧去验证这个说法。connection模型给我们提供了相应的接口PageInfo
。好的,我们加上hasNextPage
再来试一试。
query EndOfRebelShipsQuery {
rebels {
name,
originalShips: ships(first: 2) {
edges {
node {
name
}
}
pageInfo {
hasNextPage
}
}
moreShips: ships(first: 3 after: "YXJyYXljb25uZWN0aW9uOjE=") {
edges {
node {
name
}
}
pageInfo {
hasNextPage
}
}
}
}
and we get back
{
"rebels": {
"name": "Alliance to Restore the Republic",
"originalShips": {
"edges": [
{
"node": {
"name": "X-Wing" }
},
{
"node": {
"name": "Y-Wing" }
}
],
"pageInfo": {
"hasNextPage": true
}
},
"moreShips": {
"edges": [
{
"node": {
"name": "A-Wing" }
},
{
"node": {
"name": "Millenium Falcon" }
},
{
"node": {
"name": "Home One" }
}
],
"pageInfo": {
"hasNextPage": false
}
}
}
}
So on the first query for ships, GraphQL told us there was a next page,
but on the next one, it told us we’d reached the end of the connection.
我们看到第一条查询告诉我们还有下一页,第二条告诉我们到底了。
Relay uses all of this functionality to build out abstractions around
connections, to make these easy to work with efficiently without having
to manually manage cursors on the client.
Relay使用这些功能给connection做了很好的抽象,让操作变得容易且高效,不需要在客户端手动管理cursor。
Complete details on how the server should behave are
available in the GraphQL Cursor Connections spec.
服务器端应该如何处理的详细说明请见GraphQL Cursor Connections