Cursor pagination
For pipelines where offset-based pagination is impractical (large result sets, frequent inserts), the cursor helpers provide stable forward / backward pagination using opaque base64-encoded tokens.
fun <Doc : Any> MongoCollection<Doc>.cursorAggregate(
basePipeline: List<Bson>,
limit: Int,
currentCursorToken: String?,
sortFields: List<CursorSortField<Doc>>
): CursorPage<Doc>
fun <Doc : Any> MongoCollection<Doc>.cursorPageForCurrent(
current: Doc,
basePipeline: List<Bson>,
sortFields: List<CursorSortField<Doc>>
): CursorPage<Doc>
data class CursorPage<Doc>(
val data: List<Doc>,
val nextCursor: String?,
val prevCursor: String?
)
data class CursorSortField<Doc>(
val sort: Sort,
val extractor: (Doc) -> Any
)
Mechanics
sortFieldsdescribes the sort key the cursor follows. The order of fields matters: the cursor uses the same ordering to break ties.extractorreturns the value of the corresponding field on a document — used when serialising the cursor for the document at the page boundary.- Supported field types are
String,Instant,LocalDate,Long,Int,Double. cursorAggregatereturnsnextCursor/prevCursorif there are more documents in the respective direction.cursorPageForCurrentbuilds a single-document page aroundcurrent, including the prev/next tokens that would navigate from it. Useful when rendering a "detail" view that needs neighbour navigation.
Example
val sortFields = listOf(
CursorSortField(Sort.desc("createdAt"), Order::createdAt),
CursorSortField(Sort.asc("_id"), Order::id)
)
val page = orderCollection.cursorAggregate(
basePipeline = listOf(Aggregates.match(filter)),
limit = 20,
currentCursorToken = request.query("cursor"),
sortFields = sortFields
)
// page.data, page.nextCursor, page.prevCursor