@@ -3,110 +3,108 @@ import debug from 'debug';
33const log = debug ( 'mongodb-rag:index' ) ;
44
55class IndexManager {
6- constructor ( collection , options = { } ) {
7- this . collection = collection ;
8- this . options = {
9- indexName : options . indexName || 'default' ,
10- dimensions : options . dimensions || 1536 ,
11- similarity : options . similarity || 'cosine' ,
12- ...options
13- } ;
14- }
15-
16- async ensureIndexes ( ) {
17- try {
18- log ( "Checking indexes..." ) ;
19- await this . createSupportingIndexes ( ) ; // Ensure only supporting indexes
20- log ( "All indexes verified" ) ;
21- } catch ( error ) {
22- throw new Error ( `Failed to ensure indexes: ${ error . message } ` ) ;
6+ constructor ( collection , options = { } ) {
7+ this . collection = collection ;
8+ this . options = {
9+ indexName : options . indexName || 'default' ,
10+ dimensions : options . dimensions || 1536 ,
11+ similarity : options . similarity || 'cosine' ,
12+ ...options
13+ } ;
2314 }
24- }
25-
26- async createSupportingIndexes ( ) {
27- try {
28- // Index for fast document lookups
29- await this . collection . createIndex (
30- { documentId : 1 } ,
31- { name : 'document_lookup' }
32- ) ;
33-
34- // Index for metadata filtering
35- await this . collection . createIndex (
36- { 'metadata.source' : 1 , 'metadata.category' : 1 } ,
37- { name : 'metadata_filter' , sparse : true }
38- ) ;
39-
40- log ( 'Supporting indexes created successfully' ) ;
41- } catch ( error ) {
42- throw new Error ( `Failed to create supporting indexes: ${ error . message } ` ) ;
43- }
44- }
45-
46- buildSearchQuery ( embedding , filter = { } , options = { } ) {
47- const vectorSearchQuery = {
48- index : this . options . indexName ,
49- path : "embedding" ,
50- queryVector : embedding ,
51- limit : options . maxResults || 10 ,
52- exact : options . exact || false // Allow exact to be configurable
53- } ;
54-
55- // Only add numCandidates if exact is false
56- if ( ! vectorSearchQuery . exact ) {
57- vectorSearchQuery . numCandidates = options . numCandidates || 100 ;
15+
16+ async ensureIndexes ( ) {
17+ try {
18+ log ( "Checking indexes..." ) ;
19+ await this . createSupportingIndexes ( ) ; // Ensure only supporting indexes
20+ log ( "All indexes verified" ) ;
21+ } catch ( error ) {
22+ throw new Error ( `Failed to ensure indexes: ${ error . message } ` ) ;
23+ }
5824 }
59-
60- const pipeline = [
61- {
62- $vectorSearch : vectorSearchQuery
63- } ,
64- {
65- $addFields : {
66- score : { $meta : "searchScore" }
25+
26+ async createSupportingIndexes ( ) {
27+ try {
28+ // Index for fast document lookups
29+ await this . collection . createIndex (
30+ { documentId : 1 } ,
31+ { name : 'document_lookup' }
32+ ) ;
33+
34+ // Index for metadata filtering
35+ await this . collection . createIndex (
36+ { 'metadata.source' : 1 , 'metadata.category' : 1 } ,
37+ { name : 'metadata_filter' , sparse : true }
38+ ) ;
39+
40+ log ( 'Supporting indexes created successfully' ) ;
41+ } catch ( error ) {
42+ throw new Error ( `Failed to create supporting indexes: ${ error . message } ` ) ;
6743 }
68- }
69- ] ;
70-
71- // Add filter if present
72- if ( Object . keys ( filter ) . length > 0 ) {
73- pipeline [ 0 ] . $vectorSearch . filter = filter ;
7444 }
75-
76- if ( options . includeMetadata ) {
77- pipeline . push ( {
78- $project : {
79- documentId : 1 ,
80- content : 1 ,
81- metadata : 1 ,
82- score : 1
45+
46+ buildSearchQuery ( embedding , filter = { } , options = { } ) {
47+ const vectorSearchQuery = {
48+ index : this . indexName , // <-- Use configured index name
49+ path : this . embeddingFieldPath , // <-- Use configured embedding field path
50+ queryVector : embedding ,
51+ limit : options . maxResults || 10 ,
52+ exact : options . exact || false
53+ } ;
54+
55+ if ( ! vectorSearchQuery . exact ) {
56+ vectorSearchQuery . numCandidates = options . numCandidates || 100 ;
57+ }
58+
59+ const pipeline = [
60+ {
61+ $vectorSearch : vectorSearchQuery
62+ } ,
63+ {
64+ $addFields : {
65+ score : { $meta : "searchScore" }
66+ }
67+ }
68+ ] ;
69+
70+ if ( Object . keys ( filter ) . length > 0 ) {
71+ pipeline [ 0 ] . $vectorSearch . filter = filter ;
8372 }
84- } ) ;
73+
74+ if ( options . includeMetadata ) {
75+ pipeline . push ( {
76+ $project : {
77+ documentId : 1 ,
78+ content : 1 ,
79+ metadata : 1 ,
80+ score : 1
81+ }
82+ } ) ;
83+ }
84+
85+ console . log ( 'Generated search query:' , JSON . stringify ( pipeline , null , 2 ) ) ;
86+ return pipeline ;
8587 }
86-
87- console . log ( 'Generated search query:' , JSON . stringify ( pipeline , null , 2 ) ) ;
88- return pipeline ;
89- }
90-
91-
92- async getIndexStats ( ) {
93- try {
94- const stats = await this . collection . stats ( ) ;
95- const indexes = await this . collection . listIndexes ( ) . toArray ( ) ;
96-
97- return {
98- documentCount : stats . count ,
99- indexSize : stats . totalIndexSize ,
100- indexes : indexes . map ( index => ( {
101- name : index . name ,
102- size : stats . indexSizes [ index . name ] ,
103- fields : Object . keys ( index . key )
104- } ) )
105- } ;
106- } catch ( error ) {
107- throw new Error ( `Failed to get index stats: ${ error . message } ` ) ;
88+
89+
90+ async getIndexStats ( ) {
91+ try {
92+ const stats = await this . collection . stats ( ) ;
93+ const indexes = await this . collection . listIndexes ( ) . toArray ( ) ;
94+
95+ return {
96+ documentCount : stats . count ,
97+ indexSize : stats . totalIndexSize ,
98+ indexes : indexes . map ( index => ( {
99+ name : index . name ,
100+ size : stats . indexSizes [ index . name ] ,
101+ fields : Object . keys ( index . key )
102+ } ) )
103+ } ;
104+ } catch ( error ) {
105+ throw new Error ( `Failed to get index stats: ${ error . message } ` ) ;
106+ }
108107 }
109- }
110108}
111109
112110export default IndexManager ;
0 commit comments