Skip to content

Pagination ​

Pagination uses the cursor methods of an ordered query. The orderBy record sets the cursor's shape, so a cursor that does not match the ordering is a compile error.

Page through results ​

Use the last model of one page as the cursor for the next:

dart
final query = odm.users.orderBy(($) => ($.age(), $.documentId()));

final page1 = await query.limit(20).get();

if (page1.isNotEmpty) {
  final page2 = await query.startAfterObject(page1.last).limit(20).get();
}

startAfterObject reads the ordered fields (here age and the document ID) from the model. Ending the orderBy with $.documentId() gives every document a unique position, so no document is skipped or repeated when several share the same value.

Cursor methods ​

With a model:

  • startAtObject(model)
  • startAfterObject(model)
  • endAtObject(model)
  • endBeforeObject(model)

With values, as a record of the same shape as the orderBy record:

  • startAt(values)
  • startAfter(values)
  • endAt(values)
  • endBefore(values)
dart
// orderBy returns (int,), so the cursor is an (int,) record
final after1000 = await odm.users
    .orderBy(($) => ($.profile.followers(descending: true),))
    .startAfter((1000,))
    .limit(20)
    .get();

// Two fields: (int, String)
final page = await odm.users
    .orderBy(($) => ($.age(), $.name()))
    .startAfter((30, 'Jane'))
    .get();

Cursor methods return an ordered query, so you can still add where, limit or limitToLast, and call get, stream or count.