From 9a2d942835f0c06dfd59468418d5db7a0d61109e Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Fri, 5 Sep 2025 15:07:09 +0200 Subject: [PATCH] feat(MongoDB Node): Add driver info to MongoDB nodes (#18615) --- .../VectorStoreMongoDBAtlas.node.test.ts | 20 +++++++++++++++---- .../VectorStoreMongoDBAtlas.node.ts | 20 ++++++++++++++----- .../nodes/MongoDb/GenericFunctions.ts | 14 ++++++++++--- .../nodes-base/nodes/MongoDb/MongoDb.node.ts | 8 +++++--- .../nodes/MongoDb/test/MongoDB.test.ts | 6 +++++- 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts index e9a06afdb7..37275d041e 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts @@ -55,12 +55,16 @@ describe('VectorStoreMongoDBAtlas', () => { connectionString: 'mongodb://localhost:27017', }); - const client1 = await getMongoClient(mockContext); - const client2 = await getMongoClient(mockContext); + const client1 = await getMongoClient(mockContext, 1.1); + const client2 = await getMongoClient(mockContext, 1.1); expect(MockMongoClient).toHaveBeenCalledTimes(1); expect(MockMongoClient).toHaveBeenCalledWith('mongodb://localhost:27017', { appName: 'devrel.integration.n8n_vector_integ', + driverInfo: { + name: 'n8n_vector', + version: '1.1', + }, }); expect(mockClient1.connect).toHaveBeenCalledTimes(1); expect(mockClient1.close).not.toHaveBeenCalled(); @@ -81,15 +85,23 @@ describe('VectorStoreMongoDBAtlas', () => { connectionString: 'mongodb://different-host:27017', }); - const client1 = await getMongoClient(mockContext); - const client2 = await getMongoClient(mockContext); + const client1 = await getMongoClient(mockContext, 1.1); + const client2 = await getMongoClient(mockContext, 1.1); expect(MockMongoClient).toHaveBeenCalledTimes(2); expect(MockMongoClient).toHaveBeenNthCalledWith(1, 'mongodb://localhost:27017', { appName: 'devrel.integration.n8n_vector_integ', + driverInfo: { + name: 'n8n_vector', + version: '1.1', + }, }); expect(MockMongoClient).toHaveBeenNthCalledWith(2, 'mongodb://different-host:27017', { appName: 'devrel.integration.n8n_vector_integ', + driverInfo: { + name: 'n8n_vector', + version: '1.1', + }, }); expect(mockClient1.connect).toHaveBeenCalledTimes(1); expect(mockClient1.close).toHaveBeenCalledTimes(1); diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts index 7e2a9ddd92..cebca60645 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts @@ -152,6 +152,7 @@ const insertFields: INodeProperties[] = [ export const mongoConfig = { client: null as MongoClient | null, connectionString: '', + nodeVersion: 0, }; /** @@ -164,17 +165,26 @@ type IFunctionsContext = IExecuteFunctions | ISupplyDataFunctions | ILoadOptions * @param context - The context. * @returns the MongoClient for the node. */ -export async function getMongoClient(context: any) { +export async function getMongoClient(context: any, version: number) { const credentials = await context.getCredentials(MONGODB_CREDENTIALS); const connectionString = credentials.connectionString as string; - if (!mongoConfig.client || mongoConfig.connectionString !== connectionString) { + if ( + !mongoConfig.client || + mongoConfig.connectionString !== connectionString || + mongoConfig.nodeVersion !== version + ) { if (mongoConfig.client) { await mongoConfig.client.close(); } mongoConfig.connectionString = connectionString; + mongoConfig.nodeVersion = version; mongoConfig.client = new MongoClient(connectionString, { appName: 'devrel.integration.n8n_vector_integ', + driverInfo: { + name: 'n8n_vector', + version: version.toString(), + }, }); await mongoConfig.client.connect(); } @@ -198,7 +208,7 @@ export async function getDatabase(context: IFunctionsContext, client: MongoClien */ export async function getCollections(this: ILoadOptionsFunctions) { try { - const client = await getMongoClient(this); + const client = await getMongoClient(this, this.getNode().typeVersion); const db = await getDatabase(this, client); const collections = await db.listCollections().toArray(); const results = collections.map((collection) => ({ @@ -308,7 +318,7 @@ export class VectorStoreMongoDBAtlas extends createVectorStoreNode({ sharedFields, async getVectorStoreClient(context, _filter, embeddings, itemIndex) { try { - const client = await getMongoClient(context); + const client = await getMongoClient(context, context.getNode().typeVersion); const db = await getDatabase(context, client); const collectionName = getCollectionName(context, itemIndex); const mongoVectorIndexName = getVectorIndexName(context, itemIndex); @@ -358,7 +368,7 @@ export class VectorStoreMongoDBAtlas extends createVectorStoreNode({ }, async populateVectorStore(context, embeddings, documents, itemIndex) { try { - const client = await getMongoClient(context); + const client = await getMongoClient(context, context.getNode().typeVersion); const db = await getDatabase(context, client); const collectionName = getCollectionName(context, itemIndex); const mongoVectorIndexName = getVectorIndexName(context, itemIndex); diff --git a/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts b/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts index df5dacc19e..09f063eda4 100644 --- a/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts +++ b/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts @@ -153,8 +153,16 @@ export function stringifyObjectIDs(items: INodeExecutionData[]) { return items; } -export async function connectMongoClient(connectionString: string, credentials: IDataObject = {}) { +export async function connectMongoClient( + connectionString: string, + nodeVersion: number, + credentials: IDataObject = {}, +) { let client: MongoClient; + const driverInfo = { + name: 'n8n_crud', + version: nodeVersion > 0 ? nodeVersion.toString() : 'unknown', + }; if (credentials.tls) { const ca = credentials.ca ? formatPrivateKey(credentials.ca as string) : undefined; @@ -172,10 +180,10 @@ export async function connectMongoClient(connectionString: string, credentials: client = await MongoClient.connect(connectionString, { tls: true, secureContext, + driverInfo, }); } else { - client = await MongoClient.connect(connectionString); + client = await MongoClient.connect(connectionString, { driverInfo }); } - return client; } diff --git a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts index 0589496310..a5892f55ee 100644 --- a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts +++ b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts @@ -75,7 +75,9 @@ export class MongoDb implements INodeType { ); } - const client = await connectMongoClient(connectionString, credentials); + // Note: ICredentialTestFunctions doesn't have a way to get the Node instance + // so we set the version to 0 + const client = await connectMongoClient(connectionString, 0, credentials); const { databases } = await client.db().admin().listDatabases(); @@ -102,7 +104,8 @@ export class MongoDb implements INodeType { async execute(this: IExecuteFunctions): Promise { const credentials = await this.getCredentials('mongoDb'); const { database, connectionString } = validateAndResolveMongoCredentials(this, credentials); - const client = await connectMongoClient(connectionString, credentials); + const nodeVersion = this.getNode().typeVersion; + const client = await connectMongoClient(connectionString, nodeVersion, credentials); let returnData: INodeExecutionData[] = []; try { @@ -110,7 +113,6 @@ export class MongoDb implements INodeType { const items = this.getInputData(); const operation = this.getNodeParameter('operation', 0); - const nodeVersion = this.getNode().typeVersion; let itemsLength = items.length ? 1 : 0; let fallbackPairedItems: IPairedItemData[] | null = null; diff --git a/packages/nodes-base/nodes/MongoDb/test/MongoDB.test.ts b/packages/nodes-base/nodes/MongoDb/test/MongoDB.test.ts index 726e6eaa0b..a1f09b4d30 100644 --- a/packages/nodes-base/nodes/MongoDb/test/MongoDB.test.ts +++ b/packages/nodes-base/nodes/MongoDb/test/MongoDB.test.ts @@ -3,7 +3,11 @@ import { Collection, MongoClient } from 'mongodb'; import type { INodeParameters, WorkflowTestData } from 'n8n-workflow'; MongoClient.connect = async function () { - const client = new MongoClient('mongodb://localhost:27017'); + const driverInfo = { + name: 'n8n_crud', + version: '1.2', + }; + const client = new MongoClient('mongodb://localhost:27017', { driverInfo }); return client; };