mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
rebase continue
This commit is contained in:
parent
323e87825e
commit
3028a51dc7
|
@ -0,0 +1,181 @@
|
||||||
|
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);
|
||||||
|
const collection = db.collection(collectionName);
|
||||||
|
|
||||||
|
// Check if collection exists
|
||||||
|
const collections = await db.listCollections({ name: collectionName }).toArray();
|
||||||
|
if (collections.length === 0) {
|
||||||
|
db.createCollection(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',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) {}
|
|
@ -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 { Pinecone } from '@pinecone-database/pinecone';
|
||||||
import { QdrantClient } from '@qdrant/js-client-rest';
|
import { QdrantClient } from '@qdrant/js-client-rest';
|
||||||
import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow';
|
import { ApplicationError, type IDataObject, type ILoadOptionsFunctions } from 'n8n-workflow';
|
||||||
|
import { MongoClient } from 'mongodb';
|
||||||
|
|
||||||
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
|
export async function pineconeIndexSearch(this: ILoadOptionsFunctions) {
|
||||||
const credentials = await this.getCredentials('pineconeApi');
|
const credentials = await this.getCredentials('pineconeApi');
|
||||||
|
@ -67,3 +68,25 @@ export async function qdrantCollectionsSearch(this: ILoadOptionsFunctions) {
|
||||||
|
|
||||||
return { results };
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue