Skip to content

Commit

Permalink
vCore: syncs deleted documents across Table/Tree/JSON view (#2512)
Browse files Browse the repository at this point in the history
  • Loading branch information
tnaum-ms authored Dec 5, 2024
1 parent dc98abe commit 9741015
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 21 deletions.
42 changes: 41 additions & 1 deletion src/mongoClusters/MongoClusterSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type Document, type WithId } from 'mongodb';
import { EJSON } from 'bson';
import { ObjectId, type Document, type WithId } from 'mongodb';
import { type JSONSchema } from '../utils/json/JSONSchema';
import { getPropertyNamesAtLevel, updateSchemaWithDocument } from '../utils/json/mongo/SchemaAnalyzer';
import { getDataAtPath } from '../utils/slickgrid/mongo/toSlickGridTable';
Expand Down Expand Up @@ -109,6 +110,45 @@ export class MongoClustersSession {
return toSlickGridTree(this._currentRawDocuments);
}

async deleteDocuments(databaseName: string, collectionName: string, documentIds: string[]): Promise<boolean> {
const acknowledged = await this._client.deleteDocuments(databaseName, collectionName, documentIds);

if (acknowledged) {
this._currentRawDocuments = this._currentRawDocuments.filter((doc) => {
// Convert documentIds to BSON types and compare them with doc._id
return !documentIds.some((id) => {
let parsedId;
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
parsedId = EJSON.parse(id);
} catch {
if (ObjectId.isValid(id)) {
parsedId = new ObjectId(id);
} else {
parsedId = id;
}
}

/**
* deep equality for _id is tricky as we'd have to consider embedded objects,
* arrays, etc. For now, we'll just stringify the _id and compare the strings.
* The reasoning here is that this operation is used during interactive work
* and were not expecting to delete a large number of documents at once.
* Hence, the performance impact of this approach is negligible, and it's more
* about simplicity here.
*/

const docIdStr = EJSON.stringify(doc._id, { relaxed: false }, 0);
const parsedIdStr = EJSON.stringify(parsedId, { relaxed: false }, 0);

return docIdStr === parsedIdStr;
});
});
}

return acknowledged;
}

public getCurrentPageAsTable(path: string[]): TableData {
const responsePack: TableData = {
path: path,
Expand Down
16 changes: 8 additions & 8 deletions src/mongoClusters/MongoClustersClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,27 +213,27 @@ export class MongoClustersClient {
}
}

// TODO: revisit, maybe we can work on BSON here for the documentIds, and the conversion from string etc.,
// will remain in the MongoClusterSession class
async deleteDocuments(databaseName: string, collectionName: string, documentIds: string[]): Promise<boolean> {
// convert input data
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parsedDocumentIds: any[] = documentIds.map((id) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let parsedId: any;
// Convert input data to BSON types
const parsedDocumentIds = documentIds.map((id) => {
let parsedId;
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
parsedId = EJSON.parse(id);
} catch (error) {
} catch {
if (ObjectId.isValid(id)) {
parsedId = new ObjectId(id);
} else {
throw error;
throw new Error(`Invalid document ID: ${id}`);
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return parsedId;
});

// connect and extecute
// Connect and execute
const collection = this._mongoClient.db(databaseName).collection(collectionName);
const deleteResult: DeleteResult = await collection.deleteMany({ _id: { $in: parsedDocumentIds } });

Expand Down
12 changes: 7 additions & 5 deletions src/webviews/mongoClusters/collectionView/CollectionView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,11 @@ export const CollectionView = (): JSX.Element => {
return;
}

// TODO: update cached data in the controller

// TODO: update the current view, not all views.
/**
* The data on the server has been deleted and our extension code has updated its
* cache as well. Now we need to update the view locally, so that the user sees
* the changes immediately without potential focus/table resizing issues etc.
*/

setCurrentQueryResults((prev) => ({
...prev,
Expand All @@ -248,9 +250,9 @@ export const CollectionView = (): JSX.Element => {
})
.catch((error: unknown) => {
if (error instanceof Error) {
console.error('Error adding document:', error.message);
console.error('Error deleting the document:', error.message);
} else {
console.error('Unexpected error adding document:', error);
console.error('Unexpected error when deleting a document:', error);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import * as vscode from 'vscode';
import { type JSONSchema } from 'vscode-json-languageservice';
import { z } from 'zod';
import { type MongoClustersClient } from '../../../mongoClusters/MongoClustersClient';
import { MongoClustersSession } from '../../../mongoClusters/MongoClusterSession';
import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation';
import { getKnownFields, type FieldEntry } from '../../../utils/json/mongo/autocomplete/getKnownFields';
Expand Down Expand Up @@ -169,9 +168,8 @@ export const collectionsViewRouter = router({
return false;
}

const client: MongoClustersClient = MongoClustersSession.getSession(myCtx.sessionId).getClient();

const acknowledged = await client.deleteDocuments(myCtx.databaseName, myCtx.collectionName, input);
const session: MongoClustersSession = MongoClustersSession.getSession(myCtx.sessionId);
const acknowledged = await session.deleteDocuments(myCtx.databaseName, myCtx.collectionName, input);

if (acknowledged) {
showConfirmationAsInSettings(
Expand All @@ -187,9 +185,7 @@ export const collectionsViewRouter = router({
input.length,
),
);
}

if (!acknowledged) {
} else {
void vscode.window.showErrorMessage('Failed to delete documents. Unknown error.', {
modal: true,
});
Expand Down

0 comments on commit 9741015

Please sign in to comment.