如何在 Relay 中管理游标和排序?

Posted

技术标签:

【中文标题】如何在 Relay 中管理游标和排序?【英文标题】:How to manage cursors and sorting in Relay? 【发布时间】:2016-04-29 03:25:09 【问题描述】:

我们有一个 graphql 服务器(不是用 javascript 编写的)服务于对象的分页列表。我们正在尝试符合中继规范,但我们遇到了一个可以使用澄清的有趣案例。

具体来说:是否允许游标依赖于连接的其他输入?与https://github.com/graphql/graphql-relay-js/issues/20 类似,我们的连接采用一个 sort_key 参数来确定返回列表的排序顺序。根据指定的排序顺序,对象的边缘可能会返回不同的游标值(因为服务器在每种情况下都需要不同的信息来确定下一个对象)。但是,仔细阅读https://facebook.github.io/relay/docs/guides-mutations.html#range-add 表明这是不允许的;返回新创建的边的突变必须返回单个光标,该光标可以普遍应用于该边可能出现的所有可能列表? facebook是如何解决这个问题的?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。所以,我决定写一个npm 包来处理这个问题。

您可以使用fast-relay-pagination npm 包进行排序,向后和向前pagination 和过滤Mongoose 模型或MongoDB 对象。

此包通过使用MongooseMongoDB 查找和限制改进了graphql-relay 延迟加载。你肯定知道,graphql-relay's connectionFromArray 获取所有数据并对数据执行切片,这对于大量数据来说效率不高。


您可以在下面看到一个示例:

...
import 
  fetchConnectionFromArray
 from 'fast-relay-pagination'
...
export default
  type: orderConnection.connectionType,
  args: 
    ...connectionArgs,
    orderFieldName: 
      type: GraphQLString,
    ,
    sortType: 
      type: GraphQLInt,
    ,
  ,
  resolve: needAdmin(async (_, args) => 
    let orderFieldName = args.orderFieldName || '_id'
    let sortType = args.sortType || -1
    let after = args.after
    let before = args.before
    let filter = args.filter
    let first = args.first
    let last = args.last
    return fetchConnectionFromArray(
      dataPromiseFunc: SampleModel.find.bind(SampleModel), // required
      filter, // optional (for using filter on model collection) - for example => username: 'test' 
      after, //optiona
      before, // optional
      first, //optional
      last, // optional
      orderFieldName, // optional
      sortType, // optional
    )
  ),

【讨论】:

【参考方案2】:

是的,游标中应该包含足够的信息,以便能够从该点开始获取下一页(包括排序和过滤等约束),但是是否/如何执行此操作取决于您,因为它是特定于实现的.

至于突变,在您的getConfigs() 实现中,您可以在每次调用的基础上指定rangeBehaviors。因此,如果您有一个排序视图,您可能会根据排序顺序选择附加或前置。此行为指定 Relay 将在客户端执行什么操作以更新其存储。确保您的 GraphQL 服务器的代码接收到正确执行实际突变所需的所有信息(通过输入变量)仍然是您的责任。

【讨论】:

我认为我没有正确解释我的担忧,这里有一个更具体的例子:你在同一个中继分页列表上有两个视图,按不同的字段排序。相同的对象出现在两个列表中,但光标不同。你有一个突变来创建一个对象,RANGE_ADD 为两个视图指定不同的行为。服务器端的突变必须在响应中返回单个光标;它返回两个游标中的哪一个,另一个视图由于根本没有游标而做什么? 好点。我们可能没有在内部遇到这种情况,因为我们还没有在采用这种参数的连接上构建突变。让我们重新打开your original GitHub issue,看看我们是否能找到解决办法。 您可以预先添加和附加,但是例如将项目放在从上到下的第三个位置呢?例如,您有一个按名称排序的东西 [A,B,D] 并添加 C ?

以上是关于如何在 Relay 中管理游标和排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何执行 SQL 游标转换

如何在 TypeScript 中使用 Relay Modern(babel-plugin-relay 和 relay-compiler)?

如何在 GraphQL (Relay) 中查询和改变数组类型?

如何在 Relay 中捕获和处理失败的突变?

如何将 Realm 与 Relay/GraphQL 一起使用

如何在 Relay 中捕获 GraphQL 错误消息?