3

Below I've described the issue and given context. Has anyone here had this problem before? How did you solve it? Or am I just doing something wrong?

Describe the bug

When using cursor based pagination on an AppSync model list, it will return an empty items array with a NON NULLnextToken which signifies that there are more results, when I query for the next result set, it returns the 3 results that match my query and filter. I am using a limit of 10 & there are only 3 results, I'm confused to why AppSync is not returning these 3 results in my first query? (it should return the 3 results & the nextToken should be NULL)

Context:

  • I have a tabview for a screen, the first tab shows the PENDING TODO items, the second tab shows the COMPLETED TODO items.
  • I have 3 results that match my COMPLETED filter
  • I have around 36 results that match my PENDING filter

Code Snippet / Explanations

This is the query for listing the PENDING todos, as u can see there is a limit of 10 & an optional nextToken. This work as expected, I am able to paginate the results correctly.

query listTodos($nextToken: String) {
  listTodos(limit: 10, nextToken: $nextToken, filter: {
    status: {
      eq: PENDING
    }
  }) {
    nextToken,
    items {
      id
      title
      status
    }
  }
}

This is the query for listing the COMPLETED todos, as u can see there is a limit of 10 & an optional nextToken.This does not work correctly, when I first query for the todos, it returns an empty items array + a NON NULL nextToken...I then have to run another query with the given nextToken to retrieve the 3 COMPLETED todos...this must be a bug?

query listTodos($nextToken: String) {
  listTodos(limit: 10, nextToken: $nextToken, filter: {
    status: {
      eq: COMPLETED
    }
  }) {
    nextToken,
    items {
      id
      title
      status
    }
  }
}

Expected behavior

When running my listTodos query for COMPLETED todos, it should return the 3 todos in the first query, I shouldn't need to run a subsequent query with the returned nextToken to retrieve the ONLY 3 COMPLETED todos.

When doing pagination with a filter, it should return the ONLY 3 results matching the filter and return a null nextToken.

Additional context

  • Is there any other context you guys need to help debug? Let me know.

I have created an issue on the Amplify GitHub: https://github.com/aws-amplify/amplify-js/issues/6997

James111
  • 15,378
  • 15
  • 78
  • 121

1 Answers1

10

Pagination with DynamoDB can provide surprising results when providing limit and filter expressions. It has to do with when filter and limit are applied to your operation.

From the docs:

... suppose that you Query a table, with a Limit value of 6, and without a filter expression. The Query result contains the first six items from the table that match the key condition expression from the request.

Now suppose that you add a filter expression to the Query. In this case, DynamoDB reads up to six items, and then returns only those that match the filter expression. The final Query result contains six items or fewer, even if more items would have matched the filter expression if DynamoDB had kept reading more items.

It sounds like your first query operation grabs the first 10 items, then applies the filter condition, finding no matching results. Therefore, it returns no results and provides a token to resume the search operation.

For either a Query or Scan operation, DynamoDB might return a LastEvaluatedKey value if the operation did not return all matching items in the table. To get all items that match your query, take the LastEvaluatedKey value from the previous request and use it as the ExclusiveStartKey value in the next request. Repeat this until DynamoDB no longer returns a LastEvaluatedKey value.

I'm not familiar with AppSync, but it sounds like this is the behaviour you are experiencing.

Seth Geoghegan
  • 5,372
  • 2
  • 8
  • 23