在 vanilla GraphQL 中实现分页

Implementing pagination in vanilla GraphQL

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

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

编辑:值得注意的是,如果您选择使用 graphql.js.

learning GraphQL 的官方网站没有分页条目

编辑 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()
}

香草 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