fix(mongodb): avoid exact count for unfiltered queries
This commit is contained in:
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,
|
||||
|
||||
Reference in new issue
Block a user