diff --git a/packages/backend-core/src/db/lucene.ts b/packages/backend-core/src/db/lucene.ts index 9614bd6df2..fee89fcd7e 100644 --- a/packages/backend-core/src/db/lucene.ts +++ b/packages/backend-core/src/db/lucene.ts @@ -56,6 +56,7 @@ export class QueryBuilder { #version?: string #indexBuilder?: () => Promise #noEscaping = false + #skip?: number constructor(dbName: string, index: string, base?: SearchFilters) { this.#dbName = dbName @@ -138,6 +139,11 @@ export class QueryBuilder { return this } + setSkip(skip: number | undefined) { + this.#skip = skip + return this + } + excludeDocs() { this.#includeDocs = false return this @@ -468,6 +474,34 @@ export class QueryBuilder { } async run() { + if (this.#skip) { + await this.#skipPages(this.#skip) + } + return await this.#execute() + } + + async #skipPages(skip: number) { + // Lucene does not support pagination. + // Handle pagination by finding the right bookmark + const prevIncludeDocs = this.#includeDocs + const prevLimit = this.#limit + + this.excludeDocs() + const maxPageSize = 1000 + let skipRemaining = skip + do { + const toSkip = Math.min(maxPageSize, skipRemaining) + this.setLimit(toSkip) + const { bookmark } = await this.#execute() + this.setBookmark(bookmark) + skipRemaining -= toSkip + } while (skipRemaining > 0) + + this.#includeDocs = prevIncludeDocs + this.#limit = prevLimit + } + + async #execute() { const { url, cookie } = getCouchInfo() const fullPath = `${url}/${this.#dbName}/_design/database/_search/${ this.#index