Skip to content

graphQL using cursor pagination skips one record #4795

@sydneyhenrard

Description

@sydneyhenrard

Hi, we setup a graphql API using MongoTemplate and we have an issue when using pagination. Basically one record is skipped. Not really sure if it's a Spring Data Mongo or Spring GraphQL or issue on our implementaton.

The controller is setup:

    @QueryMapping
    public Window<Product> allPaginatedProducts(
        @Argument OffsetDateTime lastModified,
        ScrollSubrange subrange,
        @Argument  Optional<Sort> optionalSort
    ) {
        ScrollPosition scrollPosition = subrange.position().orElse(ScrollPosition.offset());
        Limit limit = Limit.of(subrange.count().orElse(10));
        Sort sort = optionalSort.orElse(Sort.by(Sort.Direction.ASC, "reference", "serialNumber"));
        return productRepository.getProducts(new ProductQuery(null, null, lastModified.toInstant(), "XXX"), scrollPosition, limit, sort);
    }

The repository code

    @Override
    public Window<Product> getProducts(ProductQuery productQuery, ScrollPosition scrollPosition, Limit limit, Sort sort) {
        Criteria criteria = new Criteria();
        ...

        Query query = query(criteria)
            .limit(limit)
            .with(sort)
            .with(scrollPosition);
        return mongoTemplate.query(Product.class)
            .matching(query)
            .scroll(scrollPosition);

The query

query my {
  allPaginatedProducts(first: 3) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      cursor
    }
  }
}

returns

{
  "data": {
    "allPaginatedProducts": {
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": true,
        "startCursor": "T18x",
        "endCursor": "T18z"
      },
      "edges": [
        {
          "cursor": "T18x"
        },
        {
          "cursor": "T18y"
        },
        {
          "cursor": "T18z"
        }
      ]
    }
  }
}

So now I want to get the first record after the cursor T18x, so I expected to receive T18y but I receive T18z.

query my {
  allPaginatedProducts(first: 1, after: "T18x") {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      cursor
    }
  }
}

returns

{
  "data": {
    "allPaginatedProducts": {
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": true,
        "startCursor": "T18z",
        "endCursor": "T18z"
      },
      "edges": [
        {
          "cursor": "T18z"
        }
      ]
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions