按官方文档默认是游标链接的分页方式
游标链接代码如下:
async fn numbers(
&self,
after: Option<String>,
before: Option<String>,
first: Option<i32>,
last: Option<i32>,
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
query(
after, before, first, last,
|after, before, first, last| async move {
let mut start = after.map(|after| after + 1).unwrap_or(0);
let mut end = before.unwrap_or(10000);
if let Some(first) = first {
end = (start + first).min(end);
}
if let Some(last) = last {
start = if last > end - start {
end
} else {
end - last
};
}
let mut connection = Connection::new(
start > 0,
end < 10000
);
connection.append(
(start..end)
.into_iter()
.map(|n| Edge::new(n, n as i32),
));
Ok(connection)
}).await
}
类型 Connection<usize, i32, EmptyFields, EmptyFields>
需要4个泛型参数,定义如下:
pub struct Connection<C, T, EC = EmptyFields, EE = EmptyFields> {
/// All edges of the current page.
edges: Vec<Edge<C, T, EE>>,
additional_fields: EC,
has_previous_page: bool,
has_next_page: bool,
}
-
C
游标 cursor 的类型 本例是 usize -
T
Edges.node列表数据的类型 本例是 i32 -
EC
附加数据类型 -
EE
node列表数据的附加数据类型
返回数据类型如下图

接口 numbers 接收4个可选参数 after/before/first/last
返回 pageInfo 和 edges
要改用 page pageSize 的形式改动如下:
- 原接口 after first 等4个参数 改为 page pageSize
- 增加附加数据 EC, 我们使用 PageInfo
- 修改Edges.node类型为我们实际的数据类型 DetailNode
- 使用
Connection::with_additional_fields(false, false, page_info)
的第三个参数增加附加的分页数据
PageInfo 定义如下:
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PageInfo {
pub page: i32,
pub page_size: i32,
pub total_count: i32,
}
#[Object]
impl PageInfo {
async fn page(&self) -> i32 {
self.page
}
async fn page_size(&self) -> i32 {
self.page_size
}
async fn total_count(&self) -> i32 {
self.total_count
}
}
具体实现:
async fn nodes(
&self,
ctx: &Context<'_>,
category: Option<String>, // 相关筛选参数
page: Option<i32>, // 分页参数
page_size: Option<i32>,
) -> FieldResult<Connection<i32, DetailNode, PageInfo, EmptyFields>> {
let rb = ctx.data_unchecked::<GqlState>().rbatis.clone();
let bundle = NodeBundle::Article.to_string();
let page = page.unwrap_or(1);
let page_size = page_size.unwrap_or(10);
let category = category.unwrap_or(String::from(""));
let limit = page_size;
let offset = (page - 1 ) * limit;
let mut total_count = 0;
let mut data: Vec<DetailNode> = vec!();
// 查询数据列表
if let Ok(res) = find_nodes(
rb.clone(),
&bundle,
&category,
&offset,
&limit
).await {
data = res;
}
// 获取当前筛选条件对应的数据总数
if let Ok(res) = find_nodes_count(
rb.clone(),
&bundle,
&category,
).await {
total_count = res.count;
}
// 附加分页数据
let page_info = PageInfo {
page,
page_size,
total_count
};
query(None, None, None, None,
|_after, _before, _first, _last| async move {
let mut connection = Connection::with_additional_fields(
false, false, page_info
);
connection.append(
data
.iter()
.map(|item| Edge::new(item.nid, item.clone()))
);
Ok(connection)
}
).await
}
接口类型如图:

请求示例 获取第2页2条数据如下:
