fix(mongodb): avoid exact count for unfiltered queries

This commit is contained in:
Guoyu Su authored and GitHub committed 2026-07-25 19:40:09 +08:00
1 parent 7e0f77eded
commit 3da4dd5ff9
18 files changed
+304 -36

No files matched your search

@@ -0,0 +1,24 @@
import { describe, expect, it } from "vitest";
import { canGoNextDocumentPage, resolveDocumentQueryTotals } from "@/lib/document/documentQueryTotals";
describe("document query totals", () => {
it("uses exact totals as the pagination bound", () => {
expect(resolveDocumentQueryTotals(42, true)).toEqual({
total: 42,
totalIsExact: true,
paginationTotal: 42,
});
expect(canGoNextDocumentPage({ page: 3, pageSize: 10, rowCount: 10, paginationTotal: 42 })).toBe(true);
expect(canGoNextDocumentPage({ page: 4, pageSize: 10, rowCount: 2, paginationTotal: 42 })).toBe(false);
});
it("does not use estimated totals as the pagination bound", () => {
expect(resolveDocumentQueryTotals(10_000_000, false)).toEqual({
total: 10_000_000,
totalIsExact: false,
paginationTotal: undefined,
});
expect(canGoNextDocumentPage({ page: 999_999, pageSize: 10, rowCount: 10 })).toBe(true);
expect(canGoNextDocumentPage({ page: 1_000_000, pageSize: 10, rowCount: 3 })).toBe(false);
});
});
@@ -44,7 +44,7 @@ export type DocumentStoreProvider = {
kind: DocumentStoreKind;
filterInputLabel: string;
sortInputLabel: string;
documentsLabel(options: { total: number; t: ComposerTranslation }): string;
documentsLabel(options: { total: number; totalIsExact: boolean; t: ComposerTranslation }): string;
queryPreview(options: DocumentStoreQueryPreviewOptions): string;
sortInputForColumn(column: string, direction: "asc" | "desc" | null): string;
};
@@ -80,7 +80,7 @@ const mongoDocumentProvider: DocumentStoreProvider = {
kind: "mongodb",
filterInputLabel: "find",
sortInputLabel: "sort",
documentsLabel: ({ total, t }) => t("mongo.documents", { count: total }),
documentsLabel: ({ total, totalIsExact, t }) => `${totalIsExact ? "" : "≈"}${t("mongo.documents", { count: total })}`,
queryPreview: ({ collection, filterJson, sortJson, skip, limit }) => {
const collectionRef = `db.getCollection(${JSON.stringify(collection)})`;
const parts = [`${collectionRef}.find(${mongoShellPreviewLiteral(filterJson || "{}")})`];
@@ -21,6 +21,11 @@ export interface CompleteLocalDataGridResultOptions {
hasMore?: boolean;
}
export function resolveDataGridPaginationTotal(options: { paginationTotalRowCount?: number; serverKnownTotalRowCount?: number; totalRowCountIsExact: boolean }): number | undefined {
if (options.paginationTotalRowCount !== undefined) return options.paginationTotalRowCount;
return options.totalRowCountIsExact ? options.serverKnownTotalRowCount : undefined;
}
export function hasCompleteLocalDataGridResult(options: CompleteLocalDataGridResultOptions): boolean {
if (!options.isResultsContext || options.truncated === true || options.hasMore === true) return false;
if (options.pageLimit === undefined) return true;
@@ -0,0 +1,20 @@
export interface DocumentQueryTotals {
total: number;
totalIsExact: boolean;
paginationTotal: number | undefined;
}
export function resolveDocumentQueryTotals(total: number, totalIsExact: boolean): DocumentQueryTotals {
return {
total,
totalIsExact,
paginationTotal: totalIsExact ? total : undefined,
};
}
export function canGoNextDocumentPage(options: { page: number; pageSize: number; rowCount: number; paginationTotal?: number }): boolean {
if (typeof options.paginationTotal === "number") {
return (options.page + 1) * options.pageSize < options.paginationTotal;
}
return options.rowCount >= options.pageSize;
}
@@ -645,7 +645,7 @@ export function evaluateMongoAggregateSafety(command: MongoAggregateCommand, opt
return { allowed: true };
}
export function mongoDocumentsToQueryResult(documents: unknown[], executionTimeMs: number, total: number, copyDocuments?: unknown[]): QueryResult {
export function mongoDocumentsToQueryResult(documents: unknown[], executionTimeMs: number, total: number, copyDocuments?: unknown[], totalIsExact = true): QueryResult {
const columns: string[] = [];
for (const doc of documents) {
@@ -668,6 +668,7 @@ export function mongoDocumentsToQueryResult(documents: unknown[], executionTimeM
rows,
mongo_documents: documents,
...(copyDocuments?.length === documents.length ? { mongo_copy_documents: copyDocuments } : {}),
...(totalIsExact ? {} : { total_is_exact: false }),
affected_rows: total,
execution_time_ms: Math.max(0, Math.round(executionTimeMs)),
truncated: total > documents.length,