mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Merge afe56adc0e
into d2dd1796a8
This commit is contained in:
commit
041934aaf4
|
@ -0,0 +1,180 @@
|
|||
import { MongoDBAtlasVectorSearch } from '@langchain/mongodb';
|
||||
import { MongoClient } from 'mongodb';
|
||||
import { NodeOperationError, type INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { metadataFilterField } from '@utils/sharedFields';
|
||||
import {
|
||||
mongoCollectionRLC,
|
||||
embeddingField,
|
||||
metadataField,
|
||||
vectorIndexName,
|
||||
} from '../shared/descriptions';
|
||||
import { mongoCollectionSearch } from '../shared/methods/listSearch';
|
||||
|
||||
import { createVectorStoreNode } from '../shared/createVectorStoreNode';
|
||||
|
||||
const sharedFields: INodeProperties[] = [
|
||||
mongoCollectionRLC,
|
||||
embeddingField,
|
||||
metadataField,
|
||||
vectorIndexName,
|
||||
];
|
||||
|
||||
const mongoNamespaceField: INodeProperties = {
|
||||
displayName: 'Namespace',
|
||||
name: 'namespace',
|
||||
type: 'string',
|
||||
description: 'Logical partition for documents. Uses metadata.namespace field for filtering.',
|
||||
default: '',
|
||||
};
|
||||
|
||||
const retrieveFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
options: [mongoNamespaceField, metadataFilterField],
|
||||
},
|
||||
];
|
||||
|
||||
const insertFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Clear Namespace',
|
||||
name: 'clearNamespace',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether to clear documents in the namespace before inserting new data',
|
||||
},
|
||||
mongoNamespaceField,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export class VectorStoreMongoDBAtlas extends createVectorStoreNode({
|
||||
meta: {
|
||||
displayName: 'MongoDB Atlas Vector Store',
|
||||
name: 'vectorStoreMongoDBAtlas',
|
||||
description: 'Work with your data in MongoDB Atlas Vector Store',
|
||||
icon: { light: 'file:mongodb.svg', dark: 'file:mongodb.dark.svg' },
|
||||
docsUrl:
|
||||
'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoremongodbatlas/',
|
||||
credentials: [
|
||||
{
|
||||
name: 'mongoDb',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
operationModes: ['load', 'insert', 'retrieve', 'update', 'retrieve-as-tool'],
|
||||
},
|
||||
methods: { listSearch: { mongoCollectionSearch } },
|
||||
retrieveFields,
|
||||
loadFields: retrieveFields,
|
||||
insertFields,
|
||||
sharedFields,
|
||||
async getVectorStoreClient(context, filter, embeddings, itemIndex) {
|
||||
try {
|
||||
const collectionName = context.getNodeParameter('mongoCollection', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const vectorIndexName = context.getNodeParameter('vectorIndexName', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const embeddingField = context.getNodeParameter('embedding', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const metadataField = context.getNodeParameter('metadata_field', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const credentials = await context.getCredentials('mongoDb');
|
||||
const client = new MongoClient(credentials.connectionString as string, {
|
||||
appName: 'devrel.content.n8n_vector_integ', // Added appName
|
||||
});
|
||||
await client.connect();
|
||||
const collection = client.db(credentials.database as string).collection(collectionName);
|
||||
|
||||
// test index exists
|
||||
const indexes = await collection.listSearchIndexes().toArray();
|
||||
|
||||
const indexExists = indexes.some((index) => index.name === vectorIndexName);
|
||||
|
||||
if (!indexExists) {
|
||||
throw new NodeOperationError(context.getNode(), `Index ${vectorIndexName} not found`, {
|
||||
itemIndex,
|
||||
description: 'Please check that the index exists in your collection',
|
||||
});
|
||||
}
|
||||
|
||||
return new MongoDBAtlasVectorSearch(embeddings, {
|
||||
collection,
|
||||
indexName: vectorIndexName, // Default index name
|
||||
textKey: metadataField, // Field containing raw text
|
||||
embeddingKey: embeddingField, // Field containing embeddings
|
||||
});
|
||||
} catch (error) {
|
||||
throw new NodeOperationError(context.getNode(), `Error: ${error.message}`, {
|
||||
itemIndex,
|
||||
description: 'Please check your MongoDB Atlas connection details',
|
||||
});
|
||||
}
|
||||
},
|
||||
async populateVectorStore(context, embeddings, documents, itemIndex) {
|
||||
try {
|
||||
const collectionName = context.getNodeParameter('mongoCollection', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const embeddingField = context.getNodeParameter('embedding', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const metadataField = context.getNodeParameter('metadata_field', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const vectorIndexName = context.getNodeParameter('vectorIndexName', itemIndex, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
|
||||
const credentials = await context.getCredentials('mongoDb');
|
||||
|
||||
const client = new MongoClient(credentials.connectionString as string, {
|
||||
appName: 'devrel.content.n8n_vector_integ', // Added appName
|
||||
});
|
||||
await client.connect();
|
||||
|
||||
const db = client.db(credentials.database as string);
|
||||
|
||||
// Check if collection exists
|
||||
const collections = await db.listCollections({ name: collectionName }).toArray();
|
||||
if (collections.length === 0) {
|
||||
await db.createCollection(collectionName);
|
||||
}
|
||||
const collection = db.collection(collectionName);
|
||||
await MongoDBAtlasVectorSearch.fromDocuments(documents, embeddings, {
|
||||
collection,
|
||||
indexName: vectorIndexName, // Default index name
|
||||
textKey: metadataField, // Field containing raw text
|
||||
embeddingKey: embeddingField, // Field containing embeddings
|
||||
});
|
||||
|
||||
await client.close();
|
||||
} catch (error) {
|
||||
throw new NodeOperationError(context.getNode(), `Error: ${error.message}`, {
|
||||
itemIndex,
|
||||
description: 'Please check your MongoDB Atlas connection details',
|
||||
});
|
||||
}
|
||||
},
|
||||
}) {}
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="120" height="258" viewBox="0 0 120 258" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M83.0089 28.7559C72.1328 15.9086 62.7673 2.86053 60.8539 0.150554C60.6525 -0.0501848 60.3503 -0.0501848 60.1489 0.150554C58.2355 2.86053 48.8699 15.9086 37.9938 28.7559C-55.3594 147.292 52.6968 227.287 52.6968 227.287L53.6031 227.889C54.4087 240.235 56.4228 258 56.4228 258H60.451H64.4792C64.4792 258 66.4934 240.335 67.299 227.889L68.2052 227.187C68.306 227.187 176.362 147.292 83.0089 28.7559ZM60.451 225.48C60.451 225.48 55.6172 221.365 54.3081 219.257V219.057L60.1489 89.9813C60.1489 89.5798 60.7532 89.5798 60.7532 89.9813L66.594 219.057V219.257C65.2848 221.365 60.451 225.48 60.451 225.48Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 728 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="120" height="258" viewBox="0 0 120 258" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M83.0089 28.7559C72.1328 15.9086 62.7673 2.86053 60.8539 0.150554C60.6525 -0.0501848 60.3503 -0.0501848 60.1489 0.150554C58.2355 2.86053 48.8699 15.9086 37.9938 28.7559C-55.3594 147.292 52.6968 227.287 52.6968 227.287L53.6031 227.889C54.4087 240.235 56.4228 258 56.4228 258H60.451H64.4792C64.4792 258 66.4934 240.335 67.299 227.889L68.2052 227.187C68.306 227.187 176.362 147.292 83.0089 28.7559ZM60.451 225.48C60.451 225.48 55.6172 221.365 54.3081 219.257V219.057L60.1489 89.9813C60.1489 89.5798 60.7532 89.5798 60.7532 89.9813L66.594 219.057V219.257C65.2848 221.365 60.451 225.48 60.451 225.48Z" fill="#00684A"/>
|
||||
</svg>
|
After Width: | Height: | Size: 730 B |
|
@ -68,3 +68,54 @@ export const qdrantCollectionRLC: INodeProperties = {
|
|||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const mongoCollectionRLC: INodeProperties = {
|
||||
displayName: 'MongoDB Collection',
|
||||
name: 'mongoCollection',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'From List',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
typeOptions: {
|
||||
searchListMethod: 'mongoCollectionSearch', // Method to fetch collections
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
placeholder: 'e.g. my_collection',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const vectorIndexName: INodeProperties = {
|
||||
displayName: 'Vector Index Name',
|
||||
name: 'vectorIndexName',
|
||||
type: 'string',
|
||||
default: 'vector_index',
|
||||
description: 'The name of the vector index',
|
||||
required: true,
|
||||
};
|
||||
|
||||
export const embeddingField: INodeProperties = {
|
||||
displayName: 'Embedding',
|
||||
name: 'embedding',
|
||||
type: 'string',
|
||||
default: 'embedding',
|
||||
description: 'The field with the embedding array',
|
||||
required: true,
|
||||
};
|
||||
|
||||
export const metadataField: INodeProperties = {
|
||||
displayName: 'Metadata Field',
|
||||
name: 'metadata_field',
|
||||
type: 'string',
|
||||
default: 'text',
|
||||
description: 'The text field of the raw data',
|
||||
required: true,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Pinecone } from '@pinecone-database/pinecone';
|
||||
import { QdrantClient } from '@qdrant/js-client-rest';
|
||||
import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow';
|
||||
import { MongoClient } from 'mongodb';
|
||||
|
||||
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
|
||||
const credentials = await this.getCredentials('pineconeApi');
|
||||
|
@ -67,3 +68,25 @@ export async function qdrantCollectionsSearch(this: ILoadOptionsFunctions) {
|
|||
|
||||
return { results };
|
||||
}
|
||||
|
||||
export async function mongoCollectionSearch(this: ILoadOptionsFunctions) {
|
||||
const credentials = await this.getCredentials('mongoDb');
|
||||
|
||||
const client = new MongoClient(credentials.connectionString as string, {
|
||||
appName: 'devrel.content.n8n_vector_integ',
|
||||
});
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
const db = client.db(credentials.database as string);
|
||||
const collections = await db.listCollections().toArray();
|
||||
const results = collections.map((collection) => ({
|
||||
name: collection.name,
|
||||
value: collection.name,
|
||||
}));
|
||||
|
||||
return { results };
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@
|
|||
"@langchain/google-vertexai": "0.1.8",
|
||||
"@langchain/groq": "0.1.3",
|
||||
"@langchain/mistralai": "0.2.0",
|
||||
"@langchain/mongodb": "^0.1.0",
|
||||
"@langchain/ollama": "0.1.4",
|
||||
"@langchain/openai": "0.3.17",
|
||||
"@langchain/pinecone": "0.1.3",
|
||||
|
|
Loading…
Reference in a new issue