系列导航

使用Hot Chocolate和.NET 6构建GraphQL应用文章索引

需求

GraphQL中的查询分页相对来说是查询中比较难理解的,接口的Schema也和其他不一样。在这篇文章中,我们来实现简单的查询分页。

思路

Hot Chocolate提供了两种排序方式:基于Cursor的分页和基于Offset的分页。这两种方式的区别在于:基于Cursor的分页是随结果返回每条数据的一个游标字符串,下次分页查询是通过Where子句来比较游标的大小来决定去获取哪一部分的数据;而基于Offset的方式,是类似于传统的后端分页方式,即使用OFFSET(SKIP+TAKE)方式去获取数据,后者在面对数据库会发生频繁变动(插入或删除数据)或者面对大量数据集的时候性能不如前者。但是对于基于Cursor的分页方式而言,如果对一个没有建立索引的数据列使用WhereOrder By,速度是不如Order ByOFFSET的。

在这篇文章中,我们会实现这两种不同方式的分页效果。Hot Chocolate分别提供了UsePagingUseOffsetPaging属性来完成分页需求。

实现

要使用分页属性,需要在接口上方添加UsePagingUseOffsetPaging即可,注意属性添加的顺序。

  • Query.cs
[UsePaging]
[UseProjection]
[UseFiltering]
[UseSorting]
public IQueryable<Post> GetPosts([Service] IRepository<Post> repository) => repository.GetAsQueryable();

或者

[UseOffsetPaging]
[UseProjection]
[UseFiltering]
[UseSorting]
public IQueryable<Post> GetPosts([Service] IRepository<Post> repository) => repository.GetAsQueryable();

这样就实现了查询结果的分页,同时我们可以在注入Hot Chocolate的地方进行全局配置:

builder.Services
    .AddGraphQLServer()
    .SetPagingOptions(new PagingOptions
    {
        MaxPageSize = 50,
        IncludeTotalCount = true
    })
    .AddFiltering()
    .AddProjections()
    .AddSorting()
    .AddQueryType<Query>()
    .AddType<PostType>();

下面我们来验证一下。

验证

启动Api项目,调用接口:

可以看到在返回体中数据已经按照我们指定的排序和分页结果返回了,注意在返回中包含了totalCount(这是我们在全局配置中指定一起返回的),在pageInfo中指出了是否有下一页或上一页,使用Cursor进行分页的关键之处在于返回体中还包含了每条记录的cursor值。接下来我们指定下次获取数据的起始游标值:

这样就获取了后一页的数据。

接下来我们看一下使用Offset方式分页的结果:

在这种方式下,我们看到了熟悉的skiptake参数,如果需要获取下一页数据,只需要修改skip参数即可:

总结

在本文中我们实现了查询的分页,关于分页更详细的说明请参考官方文档:Pagination。那么GraphQL的查询部分就说完了,下一篇文章将会介绍如何进行数据的修改。