【问题标题】:Implementing pagination in vanilla GraphQL在 vanilla GraphQL 中实现分页
【发布时间】:2018-07-26 19:15:41
【问题描述】:

到目前为止,我发现的每个教程都通过 Apollo、Relay 或其他一些魔术框架在 GraphQL 中实现了分页。我希望在这里找到类似问题的答案,但它们不存在。我了解如何设置查询,但我不清楚如何实现解析器。

有人能指出我正确的方向吗?如果有帮助,我正在使用 mongoose/MongoDB 和 ES5。

编辑:值得注意的是,如果您选择使用graphql.jslearning GraphQL 的官方网站没有分页条目。

编辑 2:我喜欢有 一些 人在进行研究之前投票结束问题,而其他人则利用他们的知识来帮助他人。无论你多么努力,你都无法阻止进步。 (:

【问题讨论】:

  • 你能说出你尝试过什么没有成功吗?你在哪里卡住了?
  • 我已经尝试了几乎所有可以在网上轻松找到的教程。我被困在解析器和/或边缘发挥作用的部分。
  • 你能举一个更具体的例子来说明你想要实现的目标吗?
  • @TalZ 我不确定我能做到多具体。我应该如何改进我的问题?我用howtographql.com 的链接更新了它。在那里,您将找到有关如何设置 GraphQL 服务器的教程。并非所有人都有实现分页的教程。
  • 也许您可以发布一些使用分页的 mongodb/mongoose 查询代码以及您希望能够与该分页一起使用的相关解析器。

标签: mongodb mongoose graphql ecmascript-5 graphql-js


【解决方案1】:

普通 GraphQL 中的分页

// Pagination argument type to represent offset and limit arguments
const PaginationArgType = new GraphQLInputObjectType({
  name: 'PaginationArg',
  fields: {
    offset: {
      type: GraphQLInt,
      description: "Skip n rows."
    },
    first: {
      type: GraphQLInt,
      description: "First n rows after the offset."
    },
  }
})

// Function to generate paginated list type for a GraphQLObjectType (for representing paginated response)
// Accepts a GraphQLObjectType as an argument and gives a paginated list type to represent paginated response.
const PaginatedListType = (ItemType) => new GraphQLObjectType({
  name: 'Paginated' + ItemType, // So that a new type name is generated for each item type, when we want paginated types for different types (eg. for Person, Book, etc.). Otherwise, GraphQL would complain saying that duplicate type is created when there are multiple paginated types.
  fields: {
    count: { type: GraphQLInt },
    items: { type: new GraphQLList(ItemType) }
  }
})

// Type for representing a single item. eg. Person
const PersonType = new GraphQLObjectType({
  name: 'Person',
  fields: {
    id: { type: new GraphQLNonNull(GraphQLID) },
    name: { type: GraphQLString },
  }
})

// Query type which accepts pagination arguments with resolve function
const PersonQueryTypes = {
  people: {
    type: PaginatedListType(PersonType),
    args: { 
      pagination: { 
        type: PaginationArgType, 
        defaultValue: { offset: 0, first: 10 } 
      },
    },
    resolve: (_, args) => {
      const { offset, first } = args.pagination
      // Call MongoDB/Mongoose functions to fetch data and count from database here.
      return {
        items: People.find().skip(offset).limit(first).exec()
        count: People.count()
      }
    },
  }
}

// Root query type
const QueryType = new GraphQLObjectType({
  name: 'QueryType',
  fields: {
    ...PersonQueryTypes,
  },
});

// GraphQL Schema
const Schema = new GraphQLSchema({
  query: QueryType
});

查询时:

{
  people(pagination: {offset: 0, first: 10}) {
    items {
      id
      name
    }
    count
  }
}

已创建启动板here

【讨论】:

  • 用户名签出,祝福你!
  • 很高兴能帮上忙 ;)
【解决方案2】:

您可以通过多种方式实现分页,但这里有两个使用 Mongoose 的简单示例解析器来帮助您入门:

使用限制和跳过的简单分页

(obj, { pageSize = 10, page = 0 }) => {
  return Foo.find()
    .skip(page*pageSize)
    .limit(pageSize)
    .exec()
}

使用 _id 作为光标

(obj, { pageSize = 10, cursor }) => {
  const params = cursor ? {'_id': {'$gt': cursor}} : undefined
  return Foo.find(params).limit(pageSize).exec()
}

【讨论】:

  • 感谢您提供代码 sn-ps 但我不确定如何集成它。
猜你喜欢
  • 2017-11-18
  • 2018-10-18
  • 2016-12-20
  • 1970-01-01
  • 2020-08-15
  • 2023-01-20
  • 2020-07-31
  • 2020-06-30
  • 2019-02-27
相关资源
最近更新 更多