fix(mongodb): preserve long ids in filters and updates

This commit is contained in:
zipg authored and GitHub committed 2026-07-14 11:09:11 +08:00
1 parent 2666ed1cd2
commit 2a5e7ac1c7
9 files changed
+325 -31

No files matched your search

@@ -28,7 +28,7 @@ import {
type DocumentFilterMode,
type DocumentFilterRule,
} from "@/lib/app/documentStoreProvider";
import { buildMongoInsertDocument, buildMongoUpdateDocument, formatMongoShellLiteral, parseMongoDocumentInputValue, type MongoInputValue } from "@/lib/mongo/mongoDocumentValues";
import { buildMongoInsertDocument, buildMongoUpdateDocument, formatMongoShellLiteral, mongoDocumentIdForGrid, parseMongoDocumentInputValue, serializeMongoDocumentId, type MongoInputValue } from "@/lib/mongo/mongoDocumentValues";
import { normalizeResultPageSize } from "@/lib/dataGrid/paginationPageSize";
import { useSettingsStore } from "@/stores/settingsStore";
import JsonEditNode from "./JsonEditNode.vue";
@@ -131,8 +131,9 @@ const deleteDetails = computed(() => {
if (!pending) return "";
if (pending.kind === "document") {
const id = documents.value[pending.index]?._id ?? "";
if (props.databaseType === "elasticsearch") return `Elasticsearch index: ${props.collection}\nDocument _id: ${String(id)}`;
return t("dangerDialog.mongoDocumentDetails", { collection: props.collection, id: String(id) });
const displayId = mongoDocumentIdForGrid(id);
if (props.databaseType === "elasticsearch") return `Elasticsearch index: ${props.collection}\nDocument _id: ${String(displayId)}`;
return t("dangerDialog.mongoDocumentDetails", { collection: props.collection, id: String(displayId) });
}
return t("dangerDialog.mongoFieldDetails", { field: pending.name || t("mongo.field") });
});
@@ -162,6 +163,7 @@ const gridResult = computed<QueryResult>(() => {
columns.map((col) => {
const val = doc[col];
if (val === undefined || val === null) return null;
if (col === "_id") return mongoDocumentIdForGrid(val);
if (typeof val === "object") return JSON.stringify(val);
if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") return val;
return String(val);
@@ -254,6 +256,19 @@ function clearDocumentFilters(clearLocalFilter?: (columnIndex?: number) => void)
function documentIdFromGridValue(value: MongoInputValue | undefined): string | null {
if (value === null || value === undefined) return null;
if (typeof value === "string") {
const trimmed = value.trim();
if (!trimmed) return null;
if (trimmed.startsWith('"')) {
try {
const parsed = JSON.parse(trimmed);
return typeof parsed === "string" && parsed.trim() ? parsed : trimmed;
} catch {
return trimmed;
}
}
return trimmed;
}
const parsed = parseMongoDocumentInputValue(value);
if (parsed === null || parsed === undefined) return null;
const id = typeof parsed === "object" ? JSON.stringify(parsed) : String(parsed);
@@ -307,15 +322,18 @@ async function gridSave(changes: DocumentGridChanges) {
const updateDoc = buildMongoUpdateDocument(dirtyCols, cols, documents.value[rowIdx]);
if (Object.keys(updateDoc).length === 0) continue;
await api.documentUpdateDocument(props.connectionId, props.database, props.collection, String(id), JSON.stringify(updateDoc));
const documentId = documents.value[rowIdx]?._id ?? id;
await api.documentUpdateDocument(props.connectionId, props.database, props.collection, serializeMongoDocumentId(documentId), JSON.stringify(updateDoc));
}
for (const rowIdx of changes.deletedRows) {
const row = changes.rows[rowIdx];
const id = row?.[idColIdx];
if (id == null) continue;
const routing = isEs ? documentRoutingFromDocument(documents.value[rowIdx]) : undefined;
await api.documentDeleteDocument(props.connectionId, props.database, props.collection, String(id), routing);
const document = documents.value[rowIdx];
const routing = isEs ? documentRoutingFromDocument(document) : undefined;
const documentId = isEs ? id : (document?._id ?? id);
await api.documentDeleteDocument(props.connectionId, props.database, props.collection, isEs ? String(documentId) : serializeMongoDocumentId(documentId), routing);
}
for (const newRow of changes.newRows) {
@@ -335,17 +353,10 @@ async function gridSave(changes: DocumentGridChanges) {
await load();
}
function formatMongoValue(val: unknown): string {
if (val === null || val === undefined) return "null";
if (typeof val === "number" || typeof val === "boolean") return String(val);
if (typeof val === "string") return JSON.stringify(val);
return JSON.stringify(val);
}
function mongoIdPreview(val: unknown): string {
if (val === null || val === undefined) return "null";
if (typeof val === "string" && /^[a-fA-F0-9]{24}$/.test(val)) return `ObjectId("${val}")`;
return formatMongoValue(val);
return formatMongoShellLiteral(val);
}
function elasticsearchPathIdPreview(id: string): string {
@@ -383,7 +394,7 @@ async function previewDocumentChanges(changes: DocumentGridChanges): Promise<str
stmts.push(`POST /${coll}/_update/${elasticsearchPathIdPreview(String(id))}${elasticsearchRoutingPreview(routing)}\n${JSON.stringify({ doc: updateDoc.$set ?? updateDoc }, null, 2)}`);
} else {
const updateDoc = buildMongoUpdateDocument(dirtyCols, columns, documents.value[rowIdx]);
stmts.push(`db.${coll}.updateOne({_id: ${mongoIdPreview(id)}}, ${formatMongoShellLiteral(updateDoc)})`);
stmts.push(`db.${coll}.updateOne({_id: ${mongoIdPreview(documents.value[rowIdx]?._id ?? id)}}, ${formatMongoShellLiteral(updateDoc)})`);
}
}
@@ -395,7 +406,7 @@ async function previewDocumentChanges(changes: DocumentGridChanges): Promise<str
const routing = documentRoutingFromGridRow(row, columns);
stmts.push(`DELETE /${coll}/_doc/${elasticsearchPathIdPreview(String(id))}${elasticsearchRoutingPreview(routing)}`);
} else {
stmts.push(`db.${coll}.deleteOne({_id: ${mongoIdPreview(id)}})`);
stmts.push(`db.${coll}.deleteOne({_id: ${mongoIdPreview(documents.value[rowIdx]?._id ?? id)}})`);
}
}
@@ -692,7 +703,7 @@ async function saveDoc() {
error.value = "No _id field";
return;
}
await api.documentUpdateDocument(props.connectionId, props.database, props.collection, String(id), JSON.stringify(doc), documentRoutingFromDocument(current));
await api.documentUpdateDocument(props.connectionId, props.database, props.collection, serializeMongoDocumentId(id), JSON.stringify(doc), documentRoutingFromDocument(current));
}
isEditing.value = false;
isNew.value = false;
@@ -712,7 +723,7 @@ async function applyDeleteDoc(idx: number) {
if (!id) return;
error.value = "";
try {
await api.documentDeleteDocument(props.connectionId, props.database, props.collection, String(id), documentRoutingFromDocument(doc));
await api.documentDeleteDocument(props.connectionId, props.database, props.collection, serializeMongoDocumentId(id), documentRoutingFromDocument(doc));
if (selectedIdx.value === idx) {
selectedIdx.value = null;
editJson.value = "";